Procurar um item em uma lista Lua
Pergunta
Se eu tenho uma lista de itens como este:
local items = { "apple", "orange", "pear", "banana" }
Como posso verificar se "laranja" está nesta lista?
Em Python eu poderia fazer:
if "orange" in items:
# do something
Existe um equivalente em Lua?
Solução
Você pode usar algo como um conjunto de em Lua :
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
Em seguida, você pode colocar sua lista no jogo e teste para a adesão:
local items = Set { "apple", "orange", "pear", "banana" }
if items["orange"] then
-- do something
end
Ou você pode iterar sobre a lista diretamente:
local items = { "apple", "orange", "pear", "banana" }
for _,v in pairs(items) do
if v == "orange" then
-- do something
break
end
end
Outras dicas
Use a seguinte representação em vez disso:
local items = { apple=true, orange=true, pear=true, banana=true }
if items.apple then
...
end
Você está vendo em primeira mão um dos contras da Lua ter apenas uma estrutura de dados --- você tem que rolar o seu próprio. Se você ficar com Lua você irá gradualmente acumular uma biblioteca de funções que manipulam as tabelas da maneira que você gosta de fazer as coisas. Minha biblioteca inclui uma conversão lista-to-set e uma função de lista à procura de ordem 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
tabelas Lua são mais estreitamente análogos de dicionários Python em vez de listas. A tabela que você tem criar é essencialmente uma matriz indexada com base em 1 de cordas. Usar qualquer algoritmo de busca padrão para descobrir se um valor está na matriz. Outra abordagem seria para armazenar os valores como chaves de tabela em vez como mostrado na implementação conjunto de post 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
Aqui está a função que eu uso para verificar se os dados estão em uma matriz.
tipo de solução usando metatable ...
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 é uma função swiss-armyknife você pode 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
Você pode usá-lo para verificar se existe um valor:
local myFruit = "apple"
if (table.find({"apple", "pear", "berry"}, myFruit)) then
print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1
Você pode usá-lo para encontrar a chave:
local fruits = {
apple = {color="red"},
pear = {color="green"},
}
local myFruit = fruits.apple
local fruitName = table.find(fruits, myFruit)
print(fruitName) -- "apple"
Espero que o parâmetro recursive
fala por si.
O parâmetro metatables
permite pesquisar metatables também.
O parâmetro keys
faz o olhar de função para chaves na lista. É claro que seria inútil na Lua (você pode apenas fazer fruits[key]
), mas em conjunto com recursive
e metatables
, torna-se acessível.
O parâmetro returnBool
é um salvo-guarda para quando você tem tabelas que têm false
como uma chave em uma tabela (Sim, isso é possível: fruits = {false="apple"}
)