# Swap the two largest elements in a vector

**URL:** https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234
**Category:** New to Julia
**Tags:** question, arrays, sorting
**Created:** [January 1, 2024, 7:15pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234 "2024-01-01T19:15:14Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![jcbritobr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcbritobr/32/219275_2.png) [@jcbritobr](https://discourse.julialang.org/u/jcbritobr)
#### Post date: [January 1, 2024, 7:15pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/1 "2024-01-01T19:15:14Z")

</div>

Hello, good afternoon and Happy new Year.

I would like to know how I can swap the two largest elements in a vector like [1, 2, 3, 4, 5]

---

<div class="post-metadata">

### Author: ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)
#### Post date: [January 1, 2024, 7:42pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/2 "2024-01-01T19:42:24Z")

</div>

Simple, straight-forward implementation:

```julia
function swap_largest!(v)
    L = length(v)
    L<2 && error("vector must have two elements at least")
    i1, i2 = v[1] > v[2] ? (1,2) : (2,1)
    e1, e2 = v[i1], v[i2]
    for i in 3:L
        if v[i] > e2
            if v[i] > e1
                i1, i2 = i, i1
                e1, e2 = v[i], e1
            else
                i2 = i
                e2 = v[i]
            end
        end
    end
    v[i1], v[i2] = v[i2], v[i1]
    return v
end

```

---

<div class="post-metadata">

### Author: ![mohamed.d180](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed.d180/32/52028_2.png) [@mohamed.d180](https://discourse.julialang.org/u/mohamed.d180)
#### Post date: [January 1, 2024, 8:11pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/3 "2024-01-01T20:11:08Z")

</div>

You can use :

```julia
x = [only(findall(==(x), a)) for x in sort(a)[end - 1: end]]

a[x[1]], a[x[2]] = a[x[2]], a[x[1]]

```

---

<div class="post-metadata">

### Author: ![jcbritobr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcbritobr/32/219275_2.png) [@jcbritobr](https://discourse.julialang.org/u/jcbritobr)
#### Post date: [January 1, 2024, 8:29pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/4 "2024-01-01T20:29:43Z")

</div>

I read about findmax function and was trying to build a solution with it. I’ll read about findall. Seems very neat.

---

<div class="post-metadata">

### Author: ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)
#### Post date: [January 1, 2024, 8:34pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/5 "2024-01-01T20:34:47Z")

</div>

It can also be done in a one-liner:

```julia
swap_largest2!(v) = 
  ( reverse!(@view v[Base.partialsortperm(v, 1:2; rev=true)]) ; v )

```

but the loooong version is faster I suppose (with the addition of some `@inbounds` on the `for` loop)

---

<div class="post-metadata">

### Author: ![jcbritobr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcbritobr/32/219275_2.png) [@jcbritobr](https://discourse.julialang.org/u/jcbritobr)
#### Post date: [January 1, 2024, 8:47pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/6 "2024-01-01T20:47:59Z")

</div>

very nice also. Im getting the ? help for all these functions. The @mohamed.d180 one I already understood 🙂

---

<div class="post-metadata">

### Author: ![jcbritobr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcbritobr/32/219275_2.png) [@jcbritobr](https://discourse.julialang.org/u/jcbritobr)
#### Post date: [January 1, 2024, 9:11pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/7 "2024-01-01T21:11:07Z")

</div>

marked @mohamed.d180 solution because its the simplest one. Thank you all.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [January 1, 2024, 9:16pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/8 "2024-01-01T21:16:19Z")

</div>

For simplicity:

```julia
v = collect(1:5)
i1, i2 = partialsortperm(v, 1:2; rev=true)
v[i1], v[i2] = v[i2], v[i1]

```

---

<div class="post-metadata">

### Author: ![mohamed.d180](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed.d180/32/52028_2.png) [@mohamed.d180](https://discourse.julialang.org/u/mohamed.d180)
#### Post date: [January 1, 2024, 9:20pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/9 "2024-01-01T21:20:59Z")

</div>

For variety we can use `nlargest` from `DataStructures` as follows :

```julia
using DataStructures

x = findall(!=(nothing), indexin(a, nlargest(2, a)))

a[x[1]], a[x[2]] = a[x[2]], a[x[1]]

```

---

<div class="post-metadata">

### Author: ![jcbritobr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcbritobr/32/219275_2.png) [@jcbritobr](https://discourse.julialang.org/u/jcbritobr)
#### Post date: [January 1, 2024, 10:01pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/10 "2024-01-01T22:01:43Z")

</div>

Here is the result of the code. Linear algebra is hard 😅. A dense topic

![image](https://global.discourse-cdn.com/julialang/original/3X/8/0/80312fcab8699e99b8e4e02b1480b4b9a73e9a95.png)

---

<div class="post-metadata">

### Author: ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)
#### Post date: [January 1, 2024, 11:09pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/11 "2024-01-01T23:09:23Z")

</div>

if v[i]\>=0

```julia
v=[1,3,2,5,4,7,8,6]
M1,p1=findmax(v)
v[p1]=-M1
M2,p2=findmax(v)

v[p1], v[p2]= M2, M1

```

for each v not containing missing

```julia
M1,p1=findmax(v)
v[p1]=findmin(v)[1]
M2,p2=findmax(v)
v[p1], v[p2]= M2, M1

```

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [January 1, 2024, 11:38pm UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/12 "2024-01-01T23:38:16Z")

</div>

> [@mohamed.d180](#):
>
> `x = [only(findall(==(x), a)) for x in sort(a)[end - 1: end]]`

@jcbritobr This first does a full sort of `a`, allocating a copy in the process, and then searches through `a` twice more, before doing the swap. Perhaps performance is not very important, but it’s doing a lot of unnecessary work. Especially doing a full sort is really not nice.

---

<div class="post-metadata">

### Author: ![mohamed.d180](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed.d180/32/52028_2.png) [@mohamed.d180](https://discourse.julialang.org/u/mohamed.d180)
#### Post date: [January 2, 2024, 4:50am UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/13 "2024-01-02T04:50:04Z")

</div>

If performance is important we may use this algorithm which will be of `O(n)`

```julia
function swap!(a)
    i_max = argmax(a)
    i_second = argmin(a)
    d = a[i_max] - a[i_second] # make this difference minimum to get the second max value 
    for i in 1:length(a)
        diff = a[i_max] - a[i]
        if 0 < diff < d
            i_second = i
            d = diff
        end
    end
    a[i_max], a[i_second] = a[i_second], a[i_max]
return a
end

swap!(a)

```

---

<div class="post-metadata">

### Author: ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)
#### Post date: [January 2, 2024, 7:34am UTC](https://discourse.julialang.org/t/swap-the-two-largest-elements-in-a-vector/108234/14 "2024-01-02T07:34:40Z")

</div>

fold allocates (i don’t know wy)

```julia
function swapL2(v)
    new((a,b),c)=v[c]>v[b] ? (b,c) : (v[c]>v[a] ? (c,b) : (a,b))
    p1,p2=foldl(new, 3:length(v), init=sortperm(@view v[1:2]) )
    v[p1],v[p2]=v[p2],v[p1]
    v
end

```

also this doesn’t allocate

```julia
function swapl2_(v)
    M1,p1=findmax(v)
    v[p1]=findmin(v)[1]
    M2,p2=findmax(v)
    v[p1], v[p2]= M2, M1
    v
end

```

but swapL2 is faster than swapl2\_ and both seem faster than swap!()

PS  
this reinforces in me the belief that the “appropriate” use of a functional solution (with library functions written by experts) performs better than my for loops.
