Выталкивание первого элемента из массива - PullRequest
8 голосов
/ 06 февраля 2011

У меня есть массив x в Lua. Я хотел бы установить head = x[1] и rest = остальную часть массива, чтобы rest[1] = x[2], rest[2] = x[3] и т. Д.

Как я могу это сделать?

(примечание: мне все равно, будет ли мутирован исходный массив. В Javascript я бы сделал head = x.shift(), а x будет содержать остальные элементы.)

Ответы [ 3 ]

17 голосов
/ 06 февраля 2011

head = table.remove(x, 1)

«Pop» - это неправильное название, так как оно подразумевает дешевую операцию, а удаление первого элемента таблицы требует перемещения остального содержимого- отсюда название "смещение" в JavaScript и некоторых других языках.

6 голосов
/ 06 февраля 2011

Вы хотите table.remove:

local t = {1,2,3,4}
local head = table.remove(t,1)
print( head )
--> 1
print( #t )
--> 3
print( t[1] )
--> 2

Как указывает @daurnimator, это требует больших усилий от базовой реализации массивов в среде выполнения Lua,сдвигая все элементы таблицы.Если вместо этого вы можете представлять свои массивы задом наперед, вызывая последний элемент в массиве head, то вызов table.remove() будет дешевым:

local t = {4,3,2,1}
local head = table.remove(t)
print(head)
--> 1
print( #t )
--> 3
print( t[#t] )
--> 2

В качестве альтернативы, вы можете выбрать представлениепоследовательность элементов в виде связанного списка .В этом случае удаление элемента из заголовка списка также является дешевой операцией (но не стоит вставлять элемент в конец, если вы не отслеживаете «хвост» в своем списке):

local setm,getm = setmetatable,getmetatable
local linkedlist=setm({__index={
  tail = function(l) while l.rest do l=l.rest end return l end, -- N.B. O(n)!
  push = function(l,v,t) t=l:tail() t.rest=setm({val=v},getm(l)) return t end,
  cram = function(l,v) return setm({val=v,rest=l},getm(l)) end,
  each = function(l,v)
    return function() if l then v,l=l.val,l.rest return v end end
  end
}},{ __call=function(lmeta,v,...)
  local head,tail=setm({val=v},lmeta) tail=head
  for i,v in ipairs{...} do tail=tail:push(v) end
  return head
end })

local numbers = linkedlist(1,2,3,4)
for n in numbers:each() do print(n) end
--> 1
--> 2
--> 3
--> 4

local head,rest = numbers.val, numbers.rest
print(head)
--> 1

for n in rest:each() do print(n) end
--> 2
--> 3
--> 4

local unrest = rest:cram('99')
for n in unrest:each() do print(n) end
--> 99
--> 2
--> 3
--> 4

Обратите внимание, в частности, что

local head,rest = numbers.val, numbers.rest

не изменяет никакие структуры данных, а просто дает вам дескриптор rest для определенного звена в цепочке.

0 голосов
/ 01 декабря 2018

Обычно в Lua действие вставки элемента x в последовательность ...

Например: S = {a, b, c, d, e, f} в S = {a, b,c, x, d, e, f}

... очень много времени, потому что d нужно переместить в индекс 5, e в индекс 6 и т. д.

Есть ли другиепоследовательность вида S, где S [a] = b, S [b] = c, S [c] = d, S [d] = e и S [e] = f?Таким образом, все, что вам нужно сделать, это набрать:

S [c] = x S [x] = d

и boom, x после c и перед d всего за две операции.

...