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]
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]
Simple, straight-forward implementation:
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
You can use :
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]]
I read about findmax function and was trying to build a solution with it. I’ll read about findall. Seems very neat.
It can also be done in a one-liner:
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)
very nice also. Im getting the ? help for all these functions. The @mohamed.d180 one I already understood
marked @mohamed.d180 solution because its the simplest one. Thank you all.
For simplicity:
v = collect(1:5)
i1, i2 = partialsortperm(v, 1:2; rev=true)
v[i1], v[i2] = v[i2], v[i1]
For variety we can use nlargest
from DataStructures
as follows :
using DataStructures
x = findall(!=(nothing), indexin(a, nlargest(2, a)))
a[x[1]], a[x[2]] = a[x[2]], a[x[1]]
Here is the result of the code. Linear algebra is hard . A dense topic
if v[i]>=0
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
M1,p1=findmax(v)
v[p1]=findmin(v)[1]
M2,p2=findmax(v)
v[p1], v[p2]= M2, M1
@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.
If performance is important we may use this algorithm which will be of O(n)
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)
fold allocates (i don’t know wy)
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
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.