How to find the index of the two largest values in a 1D array

Hi, I’m trying to find the index of the two largest values in an array.
I’ve been trying to work through find n smallest values in an n dims array but am getting confused because that is a 3D array.

This probably has a simple solution but it is evading me. I can’t use findmax() or argmax() since I don’t just want the largest value.

M = rand(6)

How about something like this:

julia> a = rand(6)
6-element Vector{Float64}:
 0.1911141673445511
 0.27806173115685107
 0.37965238565322046
 0.8664939772144525
 0.5317414946847623
 0.2850934557396858

julia> sortperm(a, rev=true)[1:2]
2-element Vector{Int64}:
 4
 5

Edit: @DNF’s suggestion is to use partialsortperm … which is for sure better in this case. @fatteneder’s answer is apparently faster, and allocates less.

EDIT: Updated to return the indices of the two largest values and not their values.


If linear complexity is desired then just use a loop, because they are also fast in Julia:

function findlargest2(a::AbstractVector)
    @assert length(a) >= 2
    i1, i2 = 1, 2
    max1, max2 = a[i1], a[i2]
    if max1 < max2
        max1, max2 = max2, max1
    end
    for i = 3:length(a)
        ai = a[i]
        if ai > max2
            if ai > max1
                i1, i2 = i, i1
                max1, max2 = ai, max1
            else
                i2 = i
                max2 = ai
            end
        end
    end
    return i1, i2
end
julia> x = randn(8)
8-element Vector{Float64}:
  0.8934664691033656
 -1.5294590308293632
 -0.13047453971043912
  1.8016634206952808
 -0.1771167975283893
  2.097991657439888
 -1.1881023747938395
 -0.04860363743772466

julia> findlargest2(x)
(6, 4)
2 Likes

It works, so thank you!. Why is rev = true (reverse sorting is performed)? If I make it false, the answer doesn’t make sense. Say the answer with rev = true is 4,2. I would expect the answer when rev = false to be 2,4 but the answer is 6, 5.

This will sort the entire array, which is a lot of unnecessary work. Instead, take a look at partialsortperm.

4 Likes

rev refers to the sorting order. If rev=false you will get the two smallest instead of the largest.

1 Like

using argmax(.)


M = rand(6)

i1=argmax(M)

M[i1]=-Inf

i2=argmax(M)

I believe that should be

    for i = 3:length(a)

But otherwise that is a very effective approach — non-allocating and significantly faster than partialsortperm.

1 Like

Indeed, thanks for spotting. I update my version above!