Lua: “dragging” sequence of elements within array

2019-06-24 08:15发布

问题:

I'm trying to create a function that 'drags' a sequential number of elements to a new location within the array, constrained to the current size of the array. Other items should jiggle round the 'dragged' items.

For example, if my array has 7 elements and I want to drag the middle three...

1, 2, 3, 4, 5, 6, 7  <-- keys
a, b, C, D, E, f, g  <-- values

The uppercase chars are the ones I want to 'drag'. If I drag to start of the array (drag to 1) the array would look like this:

1, 2, 3, 4, 5, 6, 7  <-- keys
C, D, E, a, b, f, g  <-- values

If I drag to position 5 (or above - can't be dragged outside current array size) the array would look like this:

1, 2, 3, 4, 5, 6, 7  <-- keys
a, b, f, g, C, D, E  <-- values

Any idea how I can achieve that using Lua in a non-crufty manner?

回答1:

Here is a version using table.move available in Lua 5.3.

It copies the group to be dragged into another table and shifts values up or down to make room for the group.

 function drag(t, src, len, dest)
    local copy = table.move(t, src, src + len - 1, 1, {})

    if src >= dest then
        table.move(t, dest, src - 1, dest + len)
    else 
        table.move(t, src + len, dest + len - 1, src)
    end

    table.move(copy, 1, len, dest, t)
 end


回答2:

function drag(t, src, len, dest)
  if len == 0 then return end
  local left, ctr, start, index, elem = math.min(src, dest), 0, 0
  local rot, size = dest - src, src + dest + len - 2 * left
  repeat
    start, index, elem = start + 1, start, t[left + start]
    repeat
      index = (index + rot) % size
      ctr, t[left + index], elem = ctr + 1, elem, t[left + index]
    until index < start
  until ctr == size
end

for K = 1, 5 do
  local tbl = {'a', 'b', 'C', 'D', 'E', 'f', 'g'}
  drag(tbl, 3, 3, K)
  print(table.concat(tbl))
end