Sobre el primer elemento de una matriz
Pregunta
Tengo una matriz x
en lua. Me gustaría establecer head = x[1]
y rest =
el resto de la matriz, de modo que rest[1] = x[2]
, rest[2] = x[3]
, etc.
¿Cómo puedo hacer esto?
(Nota: no me importa si la matriz original se muta. En JavaScript lo haría head = x.shift()
y x
contendría los elementos restantes).
Solución
"POP" es un nombre inapropiado, ya que implica una operación barata, y eliminar el primer elemento de una tabla requiere reubicar el resto del contenido, de ahí el nombre "cambio" en JavaScript y algunos otros idiomas.
Otros consejos
Usted quiere table.remove
:
local t = {1,2,3,4}
local head = table.remove(t,1)
print( head )
--> 1
print( #t )
--> 3
print( t[1] )
--> 2
Como señala @daurnimator, esto requiere mucho esfuerzo por la implementación subyacente de matrices en el tiempo de ejecución de Lua, cambiando todos los elementos de la tabla. Si puede representar sus matrices hacia atrás, llamando al último elemento en la matriz head
, entonces la llamada a table.remove()
será un pop barato:
local t = {4,3,2,1}
local head = table.remove(t)
print(head)
--> 1
print( #t )
--> 3
print( t[#t] )
--> 2
Alternativamente, puede optar por representar su secuencia de elementos como un lista enlazada. En este caso, aparecer un elemento del cabezal de la lista también es una operación barata (pero empujar uno al final no lo es, a menos que realice un seguimiento de la 'cola' en su lista):
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
Tenga en cuenta en particular que
local head,rest = numbers.val, numbers.rest
no modifica ninguna estructura de datos, pero solo le da un rest
manejar un enlace particular en la cadena.
Normalmente en lua la acción de insertar un elemento x en una secuencia ...
Eg: S = {A, B, C, D, E, F} a S = {A, B, C, X, D, E, F}
... lleva mucho tiempo porque D debe moverse al índice 5, E al índice 6, etc.
¿Hay alguna otra secuencia de la forma s donde s [a] = b, s [b] = c, s [c] = d, s [d] = e y s [e] = f? De esa manera, todo lo que tienes que hacer es escribir:
S [c] = x s [x] = D
y Boom, X está después de C y antes D en solo dos operaciones.