I have an array A=[3, 5, 1, 2, 7, 9, 10, 2, 3]
of length length(A)=9
and a set S
that contains a subset of the indices 1:9
, e.g., S=Set([1, 3, 6, 8])
. I would like to find the maximum (the value and the index) of A
over S
. That is, the maximum is 9
and the index is 6
.
I tried to do it this way
A = [3, 5, 1, 2, 7, 9, 10, 2, 3];
S = Set([1, 3, 6, 8]);
B = [if i in S A[i] else 0 end for i in 1:length(A)];
findmax(B);
but I feel like there is a better and clever way.
How about?
julia> maximum((A[i],i) for i in S)
(9, 6)
This relies on the fact that tuples are sorted in lexicographical order. This only iterates over the subset, so it should be faster when S
has significantly fewer elements than A
.
maximum
is a better choice than findmax
here as Dan Getz pointed out.
This is more verbose, but on my computer roughly 2.5x as fast as the generator solution (version 0.6):
function mymax(A, S)
val, ind = typemin(eltype(A)), -1
for i in S
val_ = A[i]
if val_ > val
val, ind = val_, i
end
end
return val, ind
end
If A
would contain no duplicates (or at least, the maximum were unique), I'd find the following more readable:
julia> i = findfirst(A, maximum(A[i] for i in S))
6
julia> A[i], i
(9, 6)
The maximum
works on a generator, so there should be no memory overhead. If S
is small, the size of A
dominates, and you have to traverse that anyway.
In case there is more maximums you could do:
function maximums(A,S)
maxvalue = maximum(A[i] for i in S)
(maxvalue, [i for i in S if A[i]==maxvalue])
end
A = [3,3,3]
S = Set([1,3])
maximums(A, S) # (3, [3, 1])
If you like to preserve order and Set is not necessary type for S then you could use unique
function:
S = unique([1,3])
maximums(A, S) # (3, [1, 3])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With