x
Luaに配列があります。、 などのように、配列の残りの部分を設定head = x[1]
したいと思います。rest =
rest[1] = x[2]
rest[2] = x[3]
これどうやってするの?
head = x.shift()
(注: 元の配列が変更されてもかまいません。Javascript では変更を行いx
、残りの要素を含めます。)
「Pop」は、安価な操作を意味するため、少し誤称です。テーブルの最初の要素を削除するには、残りのコンテンツを再配置する必要があります。そのため、JavaScriptやその他の言語では「shift」という名前が付けられています。
あなたが欲しい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
データ構造を変更することはありませんが、チェーン内の特定のリンクのハンドルを提供するだけです。