2009-03-17 33 views
40

Si tengo una lista de elementos de la siguiente manera:Buscar un elemento en una lista Lua

local items = { "apple", "orange", "pear", "banana" } 

¿cómo puedo comprobar si "naranja" se encuentra en esta lista?

En Python que podía hacer:

if "orange" in items: 
    # do something 

¿Hay un equivalente en Lua?

Respuesta

63

Usted podría utilizar algo así como un conjunto de Programming in Lua:

function Set (list) 
    local set = {} 
    for _, l in ipairs(list) do set[l] = true end 
    return set 
end 

entonces se podría poner su lista en el Conjunto y la prueba de la membresía:

local items = Set { "apple", "orange", "pear", "banana" } 

if items["orange"] then 
    -- do something 
end 

o podría iterar sobre la lista directamente :

local items = { "apple", "orange", "pear", "banana" } 

for _,v in pairs(items) do 
    if v == "orange" then 
    -- do something 
    break 
    end 
end 
4

Las tablas de Lua son análogos más cercanos de Python dictio naries en lugar de listas. La tabla que tiene crear es esencialmente una matriz indexada de cadenas basada en 1. Use cualquier algoritmo de búsqueda estándar para averiguar si hay un valor en la matriz. Otro enfoque sería almacenar los valores como claves de tabla en su lugar, como se muestra en la implementación del conjunto de la publicación de Jon Ericson.

22

utilice la siguiente representación en su lugar:

local items = { apple=true, orange=true, pear=true, banana=true } 
if items.apple then 
    ... 
end 
+2

Esta es la mejor manera de hacer un conjunto (en la matemática pura sentido) de las cosas en Lua. ¡Bravo! Sin embargo, dado que no tiene un concepto de orden, no responde necesariamente a la pregunta general de "¿Buscar un elemento en una lista de Lua?" si el orden de la lista importa – Mark

+0

Esto se siente mucho más elegante. Solo lo usé para crear una tabla que parecía '{thingIAmLookingFor: true, secondThingIAmLookingFor: true}' –

+0

Parece que no funciona con números. – CalculatorFeline

17

Estás viendo de primera mano una de las desventajas de Lua tener sólo una estructura de datos --- usted tiene que liar. Si te apegas a Lua, acumularás gradualmente una biblioteca de funciones que manipulan las tablas de la manera en que te gusta hacer las cosas. Mi biblioteca incluye una conversión de la lista-para establecer y una función de orden superior lista de búsqueda:

function table.set(t) -- set of list 
    local u = { } 
    for _, v in ipairs(t) do u[v] = true end 
    return u 
end 

function table.find(f, l) -- find element v of l satisfying f(v) 
    for _, v in ipairs(l) do 
    if f(v) then 
     return v 
    end 
    end 
    return nil 
end 
+6

Esto no es una estafa de tener una estructura de datos, es solo una estafa de Lua que tiene una biblioteca estándar horrible. –

1

tipo de solución utilizando metatabla ...

local function preparetable(t) 
setmetatable(t,{__newindex=function(self,k,v) rawset(self,v,true) end}) 
end 

local workingtable={} 
preparetable(workingtable) 
table.insert(workingtable,123) 
table.insert(workingtable,456) 

if workingtable[456] then 
... 
end 
+0

¿Cómo es esto diferente de '' 'workingtable locales = {} workingtable [123] = true workingtable [456] = true si workingtable [456] entonces ... end''' –

2
function valid(data, array) 
local valid = {} 
for i = 1, #array do 
    valid[array[i]] = true 
end 
if valid[data] then 
    return false 
else 
    return true 
end 
end 

Aquí está la función que utilizo para verificar si los datos están en una matriz.

1

Esta es una función suizo-armyknife puede utilizar:

function table.find(t, val, recursive, metatables, keys, returnBool) 
    if (type(t) ~= "table") then 
     return nil 
    end 

    local checked = {} 
    local _findInTable 
    local _checkValue 
    _checkValue = function(v) 
     if (not checked[v]) then 
      if (v == val) then 
       return v 
      end 
      if (recursive and type(v) == "table") then 
       local r = _findInTable(v) 
       if (r ~= nil) then 
        return r 
       end 
      end 
      if (metatables) then 
       local r = _checkValue(getmetatable(v)) 
       if (r ~= nil) then 
        return r 
       end 
      end 
      checked[v] = true 
     end 
     return nil 
    end 
    _findInTable = function(t) 
     for k,v in pairs(t) do 
      local r = _checkValue(t, v) 
      if (r ~= nil) then 
       return r 
      end 
      if (keys) then 
       r = _checkValue(t, k) 
       if (r ~= nil) then 
        return r 
       end 
      end 
     end 
     return nil 
    end 

    local r = _findInTable(t) 
    if (returnBool) then 
     return r ~= nil 
    end 
    return r 
end 

Usted puede utilizarlo para comprobar si un valor existe:

local myFruit = "apple" 
if (table.find({"apple", "pear", "berry"}, myFruit)) then 
    print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1 

Se puede utilizar para encontrar la clave:

local fruits = { 
    apple = {color="red"}, 
    pear = {color="green"}, 
} 
local myFruit = fruits.apple 
local fruitName = table.find(fruits, myFruit) 
print(fruitName) -- "apple" 

Espero que el parámetro recursive hable por sí mismo.

El parámetro metatables también le permite buscar metatablas.

El parámetro keys hace que la función busque las teclas en la lista. Por supuesto, eso sería inútil en Lua (puede simplemente hacer fruits[key]), pero junto con recursive y metatables, resulta útil.

El parámetro returnBool es una salvaguardia para cuando se tiene tablas que tienen false como una clave en una tabla (Sí es posible: fruits = {false="apple"})

Cuestiones relacionadas