2009-03-17 21 views
40

Se ho un elenco di elementi come questo:Cerca un elemento in un elenco Lua

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

come faccio a controllare se "orange" è in questo elenco?

In Python ho potuto fare:

if "orange" in items: 
    # do something 

Esiste un equivalente in Lua?

risposta

63

Si potrebbe usare qualcosa di simile a un set da Programming in Lua:

function Set (list) 
    local set = {} 
    for _, l in ipairs(list) do set[l] = true end 
    return set 
end 

allora si potrebbe mettere la vostra lista nel set e la prova di adesione:

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

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

Oppure si potrebbe iterare la lista direttamente :

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

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

Le tabelle Lua sono più strettamente analogiche di Python dictio nari piuttosto che liste. La tabella che hai creato è essenzialmente una matrice indicizzata basata su 1 di stringhe. Utilizzare qualsiasi algoritmo di ricerca standard per scoprire se un valore è nell'array. Un altro approccio sarebbe quello di memorizzare i valori come tasti di tabella, come mostrato nell'implementazione dell'insieme del post di Jon Ericson.

22

Utilizzare la rappresentazione seguente invece:

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

Questo è il modo migliore per fare una serie (in matematica pura senso) delle cose a Lua. Bravo! Tuttavia, dal momento che non ha alcun concetto di ordine, non risponde necessariamente alla domanda generale di "Cerca un elemento in un elenco Lua?" se l'ordine della lista è importante. – Mark

+0

Questo sembra molto più elegante. L'ho appena usato per creare un tavolo simile a '{thingIAmLookingFor: true, secondThingIAmLookingFor: true}' –

+0

Sembra non funzionare con i numeri. – CalculatorFeline

17

Stai vedendo in prima persona uno dei contro di Lua avere una sola struttura dati --- si deve rotolare il proprio. Se ti attacchi con Lua, accumulerai gradualmente una libreria di funzioni che manipolano le tabelle nel modo in cui ti piace fare le cose. La mia libreria include un elenco a impostare la conversione e una funzione di ordine superiore list-ricerca:

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

Questo non è un cono di avere una struttura dati, è solo un cono di Lua che ha una libreria standard scadente. –

1

sorta di soluzione con metatabella ...

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

Come è diverso da '' 'workingtable locale = {} workingtable [123] = true workingtable [456] = true se workingtable [456] poi ... 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 

Ecco la funzione che uso per verificare se i dati sono in una matrice.

1

Questa è una funzione swiss-armyknife è possibile utilizzare:

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 

si può utilizzare per verificare se esiste un valore:

local myFruit = "apple" 
if (table.find({"apple", "pear", "berry"}, myFruit)) then 
    print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1 

Potete usarlo per trovare la chiave:

local fruits = { 
    apple = {color="red"}, 
    pear = {color="green"}, 
} 
local myFruit = fruits.apple 
local fruitName = table.find(fruits, myFruit) 
print(fruitName) -- "apple" 

Spero che il parametro recursive parli da solo.

Il parametro metatables consente di cercare anche i metatables.

Il parametro keys fa in modo che la funzione cerchi le chiavi nell'elenco. Ovviamente questo sarebbe inutile a Lua (si può semplicemente fare fruits[key]) ma insieme a recursive e metatables, diventa utile.

Il parametro returnBool è una salvaguardia per quando si dispone di tabelle che hanno false come una chiave in una tabella (sì che sia possibile: fruits = {false="apple"})

Problemi correlati