web-dev-qa-db-fra.com

Rechercher un élément dans une liste Lua

Si j'ai une liste d'articles 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?

48
Jay

Vous pouvez 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

Ensuite, vous pouvez mettre votre liste dans l'ensemble et tester l'adhésion:

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

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

Ou vous pouvez 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
73
Jon Ericson

Utilisez plutôt la représentation suivante:

local items = { Apple=true, orange=true, pear=true, banana=true }
if items.Apple then
    ...
end
25
fsanbr

Vous voyez de première main l'un des inconvénients de Lua n'ayant qu'une seule structure de données --- vous devez lancer la vôtre. Si vous vous en tenez à Lua, vous accumulerez progressivement une bibliothèque de fonctions qui manipulent les tableaux de la manière dont vous aimez faire les choses. Ma bibliothèque comprend une conversion de liste en ensemble et une fonction de recherche de liste d'ordre 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
17
Norman Ramsey

Les tables Lua sont des analogues plus proches des dictionnaires Python plutôt que des listes. La table que vous avez créée est essentiellement un tableau indexé basé sur 1. Utilisez n'importe quel algorithme de recherche standard pour savoir si une valeur est dans le tableau. Une autre approche serait de stocker les valeurs sous forme de clés de table à la place, comme indiqué dans l'implémentation d'ensemble du message de Jon Ericson.

3
Judge Maygarden
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.

2
KingofGamesYami

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 recursive parle de lui-même.

Le paramètre metatables vous permet également de rechercher des métatables.

Le paramètre keys permet à la fonction de rechercher des clés dans la liste. Bien sûr, cela serait inutile à Lua (vous pouvez simplement faire fruits[key]) mais avec recursive et metatables, cela devient pratique.

Le paramètre returnBool est un garde-fou lorsque vous avez des tables qui ont false comme clé dans une table (Oui c'est possible: fruits = {false="Apple"})

1
Luc Bloom

Sorte 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
1