Moving array elements inside an array

What is an efficient way to move elements to a new index inside such an array?

A = collect(1:9)  # [1,2,3,4,5,6,7,8,9]

# now lets move elements 1:3 to index 2 
move!(A,1:3,2)    # [4,1,2,3,5,6,7,8,9]

# lets move the 9 to index 3 now
move!(A,9:9,3)    # [4,1,9,2,3,5,6,7,8]

# or this
move!(A,3:6,5)    # [4,1,6,7,9,2,3,5,8]

I always end up resizing the array or swap like crazy. Is there an effective (= fast) way to solve this problem?

+4
source share
2 answers

Moving a range of elements into an array to a new location can be thought of as a rotating wider range that includes the moved elements at one edge and the destination. The rotation is enough to bring the displaced elements into position and push the others away.

, . , , :

function rotate!(v,n::Int)
  l = length(v)
  l>1 || return v
  n = n % l
  n = n < 0 ? n+l : n
  n==0 && return v
  for i=1:gcd(n,l)
    tmp = v[i]
    dst = i
    src = dst+n
    while src != i
      v[dst] = v[src]
      dst = src
      src += n
      if src > l
        src -= l
      end
    end
    v[dst] = tmp
  end
  return v
end

move!(A,rng,loc) = begin 
  rotate!(view(A,min(first(rng),loc):max(last(rng),length(rng)+loc-1)),first(rng)-loc)
  return A
end

A = collect(1:9)
@show move!(A,1:3,2) == [4,1,2,3,5,6,7,8,9]
@show move!(A,9:9,3) == [4,1,9,2,3,5,6,7,8]
@show move!(A,3:6,5) == [4,1,6,7,9,2,3,5,8]

. , view , rotate! .

+4

- ?

function flipvals!(A, ind1, ind2)
     flip = view.(A, [ind1,ind2])
     flip .= reverse(flip)
     return nothing
end

permute! @DNF .

: OP , :

A[ind1], A[ind2] = A[ind2], A[ind1]
+1

Source: https://habr.com/ru/post/1672554/


All Articles