Rechercher un élément dans une liste Lua
Question
Si j'ai une liste d'éléments comme celui-ci:
local items = { "apple", "orange", "pear", "banana" }
comment vérifier si " orange " est dans cette liste?
En Python, je pourrais faire:
if "orange" in items:
# do something
Y a-t-il un équivalent à Lua?
La solution
Vous pourriez utiliser quelque chose comme un ensemble de Programmation en Lua :
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
Vous pouvez ensuite placer votre liste dans l'ensemble et tester votre adhésion:
local items = Set { "apple", "orange", "pear", "banana" }
if items["orange"] then
-- do something
end
Vous pouvez également parcourir la liste directement:
local items = { "apple", "orange", "pear", "banana" }
for _,v in pairs(items) do
if v == "orange" then
-- do something
break
end
end
Autres conseils
Utilisez plutôt la représentation suivante:
local items = { apple=true, orange=true, pear=true, banana=true }
if items.apple then
...
end
Vous voyez vous-même l'un des inconvénients de Lua avec une seule structure de données: vous devez rouler la vôtre. Si vous vous en tenez à Lua, vous accumulerez progressivement une bibliothèque de fonctions qui manipulent les tableaux comme vous le souhaitez. Ma bibliothèque comprend une conversion de liste à ensemble et une fonction de recherche de liste de rang supérieur:
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
Les tables Lua sont plus proches des dictionnaires Python que des listes. La table que vous avez créée est essentiellement un tableau de chaînes indexé basé sur 1. Utilisez n'importe quel algorithme de recherche standard pour savoir si une valeur est dans le tableau. Une autre approche consisterait à stocker les valeurs sous forme de clés de table, comme indiqué dans l’implémentation de la publication 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
Voici la fonction que j'utilise pour vérifier si les données sont dans un tableau.
Type de solution utilisant 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
Il s’agit d’une fonction swiss-armyknife que vous pouvez utiliser:
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
Vous pouvez l'utiliser pour vérifier si une valeur existe:
local myFruit = "apple"
if (table.find({"apple", "pear", "berry"}, myFruit)) then
print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1
Vous pouvez l'utiliser pour trouver la clé:
local fruits = {
apple = {color="red"},
pear = {color="green"},
}
local myFruit = fruits.apple
local fruitName = table.find(fruits, myFruit)
print(fruitName) -- "apple"
J'espère que le paramètre récursif
parle pour lui-même.
Le paramètre metatables
vous permet également de rechercher des méta-tables.
Le paramètre keys
permet à la fonction de rechercher des clés dans la liste. Bien sûr, cela serait inutile dans Lua (vous pouvez simplement faire fruits [clé]
), mais avec récursif
et méta-tables
, cela devient pratique.
Le paramètre returnBool
est un garde-fou pour les tables dont la clé est false
dans une table (oui, c'est possible: fruits = { false = " apple &};}
)