Findfirst alternative for Set

Hi there,

I am wondering whether there is something similar to findfirst which does not return the index, but the matching object itself.

This would be useful to work with Sets

julia> findfirst(x->x==1,Set([1,2,3]))
ERROR: MethodError: no method matching keys(::Set{Int64})

Closest candidates are:
  keys(::DataStructures.Accumulator)
   @ DataStructures ~/.julia/packages/DataStructures/59MD0/src/accumulator.jl:58
  keys(::Base.Pairs)
   @ Base iterators.jl:318
  keys(::Tuple)
   @ Base tuple.jl:71
  ...

Stacktrace:
 [1] pairs(collection::Set{Int64})
   @ Base ./abstractdict.jl:172
 [2] findfirst(testf::var"#11#12", A::Set{Int64})
   @ Base ./array.jl:2115
 [3] top-level scope
   @ REPL[25]:1
1 Like

You could just test for membership:

julia> 1 in Set([1,2,3])
true

Or, if you need to match on more complex criteria:

julia> any(mymatchfun, Set([1,2,3]))
true

(Hmm, but that doesn’t give you the object itself.)

Maybe you can give an example use-case which does not trivially reduce to a simple membership test?

1 Like
function myfindfirst(f, s::Set)
   for i in s
       f(i) && return i
   end
   return nothing
end

is what you’re looking after ?

I guess the concept of finding the ‘first’ element that matches something in a set, doesn’t make sense, since sets are not ordered. It would be more akin to random sampling.

3 Likes

thank you all very much.

I was hoping that there already exists something. But indeed. As the set is random, the name findfirst does not make much sense. Still the feature is useful and I very much like the simplicity of the myfindfirst function

You can also use first(Iterators.filter(==(1), s)). Note that this throws an error if no match is found. You can use first(..., 1) to get a 1-element vector if it is found and a 0-element vector if not.

2 Likes

This thread is effectively asking the same question: Standard way to get first element of iterator satisfying predicate - #12 by simeonschaub

2 Likes