In Julia I can use argmax(X)
to find max element. If I want to find all element satisfying condition C
I can use findall(C,X)
. But how can I combine the two? What's the most efficient/idiomatic/concise way to find maximum index satisfying some condition in Julia?
CodePudding user response:
From what I understand from your question you can use findmax()
(requires Julia >= v1.7) to find the maximum index on the result of findall()
:
julia> v = [10, 20, 30, 40, 50]
5-element Vector{Int64}:
10
20
30
40
50
julia> findmax(findall(x -> x > 30, v))[1]
5
Performance of the above function:
julia> v = collect(10:1:10_000_000);
julia> @btime findmax(findall(x -> x > 30, v))[1]
33.471 ms (10 allocations: 77.49 MiB)
9999991
Update: solution suggested by @dan-getz of using last()
and findlast()
perform better than findmax()
but findlast()
is the winner:
julia> @btime last(findall(x -> x > 30, v))
19.961 ms (9 allocations: 77.49 MiB)
9999991
julia> @btime findlast(x -> x > 30, v)
81.422 ns (2 allocations: 32 bytes)
CodePudding user response:
If you'd like to avoid allocations, filtering the array lazily would work:
idx_filtered = (i for (i, el) in pairs(X) if C(el))
argmin(i -> X[i], idx_filtered)
Unfortunately, this is about twice as slow as a hand-written version (in my testing):
function byhand(X, C)
start = findfirst(C, X)
(start == nothing) && return nothing
imax, max = start, X[start]
for i = start:lastindex(X)
if C(X[i]) && X[i] > max
imax, max = i, X[i]
end
end
imax, max
end