Removing the elements of one array from another using setdiff

Hi fellows,

The following code works:

a = [1,2,3,4,5]
b = [4,5,6]
setdiff(a,b)
3-element Array{Int64,1}:
 1
 2
 3

However this one doesn’t:

type X
           a::Int
 end
Base.broadcast(::typeof(==),x::X,y::X) = x.a == y.a
a = [X(1),X(2),X(4),X(5),X(6)]
b = [X(4),X(5),X(6)]
setdiff(a,b)
5-element Array{X,1}:
 X(1)
 X(2)
 X(4)
 X(5)
 X(6)

What went wrong here?

I’m on julia 0.6.2. I think this is what you might want to do in your code instead of the broadcast thing.

import Base.==
==(x::X,y::X) = x.a == y.a

This gives you X(1) == X(1), not the broadcast function.
But this still cannot give you the setdiff result you want, at least on my julia v0.6.2. As the result is totally random on my julia 0.6.2. Sometime the result is a four element Array, sometime the result is a five element one.

I try to further dig into the issue. setdiff(a, b) leads to in(a_elem, bset) leads to haskey(bset.dict, a_elem), where bset = Set(b). And the following happens:

julia> haskey(Set(b).dict, Y(5))
false

julia> haskey(Set(b).dict, Y(5))
false

julia> haskey(Set(b).dict, Y(5))
true

So I think this problem is related to the dictionary in julia 0.6.2. I may have seen some issues similar to this before and the solution to it, and I will try to search for that.

I suspect the reason is because type is mutable so even though the as are the same, the objects aren’t equal. Try immutable.

julia> type mtest
       a::Int
       end

julia> immutable itest
       a::Int
       end

julia> m1 = mtest(1); m2 = mtest(1); m1 == m2
false

julia> i1 = itest(1); i2 = itest(1); i1 == i2
true
1 Like

immutable instead of type solves the problem on julia 0.6.2.
And the problem of type seems to relate to this:
https://github.com/JuliaLang/julia/issues/12198

Yep. That seems to be the case.

julia> m1 = [mtest(i) for i in 1:5]; m2 = [mtest(i) for i in 4:5]; setdiff(m1,m2)
5-element Array{mtest,1}:
 mtest(1)
 mtest(2)
 mtest(3)
 mtest(4)
 mtest(5)

julia> i1 = [itest(i) for i in 1:5]; m2 = [itest(i) for i in 4:5]; setdiff(i1,i2)
3-element Array{itest,1}:
 itest(1)
 itest(2)
 itest(3)