Extraire le premier élément d'un tableau
Question
j'ai un tableau x
en Lua.Je voudrais définir head = x[1]
et rest =
le reste du tableau, de sorte que rest[1] = x[2]
, rest[2] = x[3]
, etc.
Comment puis-je faire ceci?
(note:Je m'en fiche si le tableau d'origine est muté.En Javascript je ferais head = x.shift()
et x
contiendrait les éléments restants.)
La solution
"POP" est un peu inapproprié, car il implique une opération bon marché, et la suppression du premier élément d'une table nécessite de relocaliser le reste du contenu - d'où le nom "Shift" en JavaScript et d'autres langues.
Autres conseils
Tu veux table.remove
:
local t = {1,2,3,4}
local head = table.remove(t,1)
print( head )
--> 1
print( #t )
--> 3
print( t[1] )
--> 2
Comme le souligne @Daurnimator, cela nécessite beaucoup d'efforts par la mise en œuvre sous-jacente des tableaux dans le runtime LUA, en déplacement de tous les éléments de la table. Si vous pouvez à la place représenter vos tableaux vers l'arrière, appelant le dernier élément du tableau head
, alors l'appel à table.remove()
sera une pop bon marché:
local t = {4,3,2,1}
local head = table.remove(t)
print(head)
--> 1
print( #t )
--> 3
print( t[#t] )
--> 2
Alternativement, vous pouvez choisir de représenter votre séquence d'éléments comme un liste liée. Dans ce cas, faire éclater un élément de la tête de la liste est également une opération bon marché (mais en pousser un à la fin, à moins que vous ne gardiez une trace de la «queue» dans votre liste):
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
Noter en particulier que
local head,rest = numbers.val, numbers.rest
ne modifie aucune structure de données mais vous donne simplement un rest
gérer un lien particulier dans la chaîne.
Normalement en Lua l'action d'insérer un élément x dans une séquence...
Par exemple:S={a,b,c,d,e,f} à S={a,b,c,x,d,e,f}
... prend beaucoup de temps car d doit être déplacé vers l'index 5, e vers l'index 6, etc.
Y a-t-il une autre séquence de la forme s où s [a] = b, s [b] = c, s [c] = d, s [d] = e et s [e] = f?De cette façon, il vous suffit de taper :
S [c] = x s [x] = d
et boum, x est après c et avant d en seulement deux opérations.