Finding Position of Element in an Array

But you still didn’t read the documentation… this would work:

a = [ "a", "b", "c", "d" ]
findfirst(isequal("c"), a)
6 Likes

Slightly neater and more legible than my reinvention of the isequal function …

Thank you.

But there is a difference between not reading the documentation, which is in the link below and does not mention “isequal” anywhere, and not knowing how to combine different functions to obtain the desired result.

https://docs.julialang.org/en/v1/base/strings/#Base.findfirst-Tuple{AbstractString,AbstractString}

That’s the link to searching inside a string. You are searching in an array.

Here you go: https://docs.julialang.org/en/v1/base/arrays/#Base.findfirst-Tuple{Function,Any}

2 Likes

As @DNF pointed out, you were looking at the docs for another method.

In general, it is better to use ?findfirst at the REPL, that way you don’t miss the right method.

2 Likes

@nilshg: isequal and == are not the same. You can read about the difference in the isequal doumentation. In this case you could also write findfirst(==("c"), a) to get the same result.

2 Likes

findall command does not work at all.

v=rand(Float64,3);
C = findall(x->x==min(v), v)

julia> v=rand(3)
3-element Array{Float64,1}:
 0.09242010387818334
 0.0444175027161271
 0.32294884973200766

julia> C = findall(x->x==min(v), v)
ERROR: MethodError: no method matching min(::Array{Float64,1})

how can we find the minimal value position in Julia?

Please try to read the error message. It tells you what’s wrong, it doesn’t have anything to do with findall, but with min. Use minimum instead.

If you only need the position of the first minimum (not all of them), you can use findmin(v) instead.

3 Likes

I think that would call minimum for every comparison though, which may not be efficient. Something like

findall(isequal(minimum(v)), v)

could avoid that.

3 Likes

Thanks you @Tamas_Papp

Since you said “the minimal position”, maybe you could use argmin:

help?> argmin
search: argmin

  argmin(itr) -> Integer

  Return the index of the minimum element in a collection. If there are multiple minimal elements, then the first one will be returned.

just to cooperate with the discusion, some benchmarks:

v = rand(10000)
julia> @btime argmin(v)
  18.699 μs (0 allocations: 0 bytes)
443
julia> @btime findall(isequal(minimum(v)), v)
  32.300 μs (8 allocations: 320 bytes)
1-element Array{Int64,1}:
 443
julia> @btime findmin(v)
  18.699 μs (1 allocation: 32 bytes)
(7.175518611357568e-5, 443)
julia> @btime findall(x->x==minimum(v), v)
  239.807 ms (20006 allocations: 312.77 KiB)
1-element Array{Int64,1}:
 443

obviusly this applies with the max versions too, so is good to know who actually performs faster.

2 Likes

the local minimum or global minimum is also a question.

All methods gives the global minimum xi that xi <= xj for all xj in a vector x, but findmin and argmin throw the first global min they can find, for example:

x=[1,2,3,4,1]

julia> findmin([1,2,3,4,1])
(1, 1)
julia> argmin([1,2,3,4,1])
1

but:

julia> findall(isequal(minimum(x)),x)
2-element Array{Int64,1}:
 1
 5
3 Likes

How can you avoid memory allocation by using findall in a loop?
I have a loop which goes upto 100000 and each time it finds the index of numbers matching a certain criteria.
This is what I am talking about:
for i = 1:100000; cr = max(0.0, 0.2*sqrt(i) - 20); ftt = findall(x .<= cr); end

x is an array of floats.

how is cr an array?..

maybe you can sort array and find first, since find needs to make comparison

Sorry, I have just edited. x is an array of floats

Pass findall a predicate so it doesn’t need to allocate the temporary x .<= cr array, i.e. findall(xi -> xi <= cr, x). This produced a ~3x speedup on my machine.

1 Like

Just to say that I wish in v2 we’d have a simpler API for this - most languages have something in the line of indexof, where you get the index or -1 if not found (so it would also be type stable). In Julia one is forced to do some weird gymnastics involving some form of find* and Some. It was quite difficult to understand how to use these (when the previous function was deprecated) and I almost never know how to do it without checking the docs – or rather just searching and copying my code. In my humble opinion, t’s not developer friendly.

(PS - off topic but related - OMG how I wish there would be another name for occursin. Oh the time I spent trying to remember the name of this function! “To occur” is really not a commonly used English verb and it’s really hard for a non-native English speaker to remember it. I honestly had to repeat it 100 times at some point, exasperated, to commit it to memory).

2 Likes

You only have to use Some if nothing is a valid index which is quite rare. Otherwise just find / findall away?

julia> a = [1,2,3,4,5];

julia> findall(isequal(3), a)
1-element Array{Int64,1}:
 3

julia> findfirst(isequal(3), a)
3

What would a simpler API be?