Possibility to check `∈` and `∉` in the `===` sense


#1

As reported in the Julia documentation, the in, , , , functions “determine whether an item is in the given collection, in the sense that it is == to one of the values generated by iterating over the collection”.

I need to filter out all entries of a dictionary with value equal to either nothing or false. The following command filters out also entries with value equal to 0, which instead I need to keep:

a = Dict("a"=>1, "b"=>0, "c"=>false, "d"=>2, "e"=>"test", "f"=>nothing)
filter(x -> x.second ∉ (false, nothing), a)

This is a possible workaround:

filter(x -> x.second !== false && x.second !== nothing, a)

but in my opinion it would be useful to define analogous functions working in the === sense, which could for instance be named in=, ∈=, ∋=, ∉=, ∌=. Their documentation would also better clarify how in, , , , behave in these cases, helping to avoid similar bugs.


#2

You could always define this if you want (in 0.7):

∈₌(x, collection) = any(y -> x === y, collection)

#3

Or write the original as

filter(x -> any(last(x) .≢ (false, nothing)), a)

#4

(That allocates a temporary array (to pass to any ) for every element x of a, which is pretty inefficient for large a. Though it’s not clear that the original poster cares about performance here.)


#5

You need to use all not any.


#6

It is really interesting that original poster workaround seems to be 5 times faster than your solution!

0.7.0-beta2.83> t1() = filter(x -> x.second !== false && x.second !== nothing, a);
0.7.0-beta2.83> t2() = filter(x -> all(last(x) .≢ (false, nothing)), a);
0.7.0-beta2.83> t3() = let out=(false, nothing); filter(x -> all(last(x) .≢ out), a) end;
0.7.0-beta2.83> t4() = let out=[false, nothing]; filter(x -> all(last(x) .≢ out), a) end;
0.7.0-beta2.83> t5() = filter(x -> x ∈₌(false, nothing), a);

0.7.0-beta2.83> @btime t1();
  351.200 ns (4 allocations: 608 bytes)

0.7.0-beta2.83> @btime t2();
  4.107 μs (30 allocations: 1.21 KiB)

0.7.0-beta2.83> @btime t2();
  4.032 μs (30 allocations: 1.21 KiB)

0.7.0-beta2.83> @btime t3();
  4.030 μs (37 allocations: 1.32 KiB)

0.7.0-beta2.83> @btime t4();
  12.642 μs (46 allocations: 27.10 KiB)

0.7.0-beta2.83> @btime t5();
  1.887 μs (10 allocations: 704 bytes)

I am surprised that let did not help. What did I do wrong?

BTW I would expect that compiler optimize allocating in Tamas’s solution. Maybe in future version of julia?