2009-03-17 11 views
40

Si j'ai une liste d'articles comme celui-ci:Rechercher un élément dans une liste Lua

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

comment puis-je vérifier si « orange » est dans cette liste?

En Python je pouvais faire:

if "orange" in items: 
    # do something 

Y at-il un équivalent en Lua?

Répondre

63

Vous pouvez utiliser quelque chose comme un ensemble de Programming in 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 le jeu et le test d'adhésion:

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

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

Ou vous pourriez itérer sur la liste directement :

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

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

Les tables Lua sont plus proches de Python dictio naires plutôt que des listes. La table que vous avez créée est essentiellement un tableau indexé de chaînes 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 en tant que clés de table à la place, comme indiqué dans la mise en œuvre de la publication de Jon Ericson.

22

Utilisez la représentation suivante à la place:

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

C'est la meilleure façon de faire un ensemble (dans la mathématique pur sens) des choses à Lua. Bravo! Cependant, comme il n'a pas de concept d'ordre, il ne répond pas nécessairement à la question générale de "Rechercher un objet dans une liste Lua?" si l'ordre de la liste est important. – Mark

+0

Cela semble tellement plus élégant. Je l'ai juste utilisé pour créer une table qui ressemblait à '{thingIAmLookingFor: true, secondThingIAmLookingFor: true}' –

+0

Ne semble pas fonctionner avec les nombres. – CalculatorFeline

17

Vous voyez de première main l'un des inconvénients de Lua ayant une seule structure de données --- vous devez rouler votre propre. Si vous vous en tenez à Lua, vous accumulez progressivement une bibliothèque de fonctions qui manipulent les tables de la manière dont vous aimez faire les choses. Ma bibliothèque comprend une liste de conversion mis à et une fonction de liste recherche 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 
+6

Ce n'est pas un con d'avoir une structure de données, c'est juste un con de Lua ayant une bibliothèque standard merdique. –

1

Trier de la solution en utilisant métatable ...

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

Comment est-ce différent de '' 'workingtable locale = {} workingtable [123] = true workingtable [456] = true si workingtable [456] puis ... 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 

Voici la fonction que j'utilise pour vérifier si les données sont dans un tableau.

1

Cette fonction suisse-armyknife 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étabalises.

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

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

Questions connexes