2011-02-05 17 views
5

Tengo una matriz x en Lua. Me gustaría establecer head = x[1] y rest = el resto de la matriz, de manera que rest[1] = x[2], rest[2] = x[3], etc.Saltando el primer elemento de una matriz

¿Cómo puedo hacer esto?

(nota: no me importa si la matriz original se mutó en Javascript que haría head = x.shift() y x contendría los elementos restantes..)

Respuesta

12

head = table.remove(x, 1)

"pop" es un poco de un nombre inapropiado, ya que implica una operación barata, y eliminar el primer elemento de una tabla requiere reubicar el resto de los contenidos, de ahí el nombre "shift" en JavaScript y algunos otros idiomas.

+1

Nota: para una matriz de cualquier tamaño razonable, esta es una operación MUY lenta; intenta y reconsidera por qué quieres hacer esto ... – daurnimator

+3

@daurnimator te refieres a "matriz de _un tamaño irrazonable_" B-) –

+0

En lugar de reconsiderar la motivación para esto, considera quizás usar una estructura de datos que no sea una matriz. Una lista enlazada (fácil de crear en Lua) hace que esta sea una operación barata, a expensas de más almacenamiento necesario para cada nodo. – Phrogz

3

¿Quieres 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 @daurnimator señala, esto requiere mucho esfuerzo por parte de la implementación subyacente de matrices en el tiempo de ejecución de Lua, cambiando todos los elementos de la tabla. Si en su lugar puede representar sus matrices hacia atrás, llamando el último elemento de 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, usted puede optar por representar a su secuencia de elementos como linked list . En este caso, haciendo estallar un elemento de la cabeza de la lista es también una operación barata (pero empujando uno en el extremo no lo es, a menos que mantener un registro de la 'cola' de la 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 

Nota en particular, que

no modifica cualquier estructura de datos, pero sólo te da un mango rest en un enlace especial en la cadena.

Cuestiones relacionadas