2011-02-05 6 views
5

У меня есть массив x в Lua. Я хотел бы установить head = x[1] и rest = остальной части массива, так что rest[1] = x[2], rest[2] = x[3] и т.д.Выбирая первый элемент из массива

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

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

ответ

12

head = table.remove(x, 1)

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

+1

Примечание: для массива любого разумного размера это ОЧЕНЬ медленная операция; попробуйте и передумайте, почему вы хотите это сделать ... – daurnimator

+3

@daurnimator вы имеете в виду «массив из _any unreasonable_ size» B-) –

+0

Вместо того, чтобы пересматривать мотивацию для этого, вместо этого подумайте, возможно, используя структуру данных, отличную от массива. Связанный список (простой в создании в Lua) делает эту дешевую операцию за счет большего объема памяти, необходимой для каждого узла. – Phrogz

3

Вы хотите 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 

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

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 

Примечания в частности, что

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

Смежные вопросы