Buscar un artículo en una lista de Lua
Pregunta
Si tengo una lista de elementos como este:
local items = { "apple", "orange", "pear", "banana" }
¿Cómo verifico si " naranja " está en esta lista?
En Python podría hacer:
if "orange" in items:
# do something
¿Hay un equivalente en Lua?
Solución
Podría usar algo como un conjunto de Programación en Lua :
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
Entonces podría poner su lista en el Conjunto y probar 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
Otros consejos
Utilice la siguiente representación en su lugar:
local items = { apple=true, orange=true, pear=true, banana=true }
if items.apple then
...
end
Estás viendo de primera mano una de las desventajas de que Lua tiene una sola estructura de datos: tienes que rodar la tuya. Si te quedas con Lua, acumularás gradualmente una biblioteca de funciones que manipulan las tablas de la forma en que te gusta hacer las cosas. Mi biblioteca incluye una conversión de lista a conjunto y una función de búsqueda de lista de orden superior:
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
Las tablas Lua son más análogas a los diccionarios de Python que a las listas. La tabla que ha creado 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, como se muestra en la implementación establecida de la publicación de Jon Ericson.
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 uso para verificar si los datos están en una matriz.
Tipo de solución usando 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
Esta es una función navaja suiza que puedes usar:
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
Puede usarlo para verificar si existe un valor:
local myFruit = "apple"
if (table.find({"apple", "pear", "berry"}, myFruit)) then
print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1
Puede usarlo 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 recursivo
hable por sí mismo.
El parámetro metatables
también le permite buscar metatables.
El parámetro keys
hace que la función busque teclas en la lista. Por supuesto, eso sería inútil en Lua (puede hacer fruits [key]
) pero junto con recursive
y metatables
, se vuelve útil.
El parámetro returnBool
es una protección para cuando tiene tablas que tienen false
como clave en una tabla (Sí, eso es posible: fruits = { false = " manzana "}
)