2009-03-17 13 views
40

Jeśli mam listę elementów takiego:Wyszukiwanie elementu na liście Lua

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

jak mogę sprawdzić, czy „pomarańczowy” jest w tym liście?

w Pythonie mogę zrobić:

if "orange" in items: 
    # do something 

Czy istnieje odpowiednik w Lua?

Odpowiedz

63

Można użyć coś takiego zestawu z Programming in Lua:

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

Następnie można umieścić swoją listę w zestawie oraz testu dla członkostwa:

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

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

Albo można iteracyjne nad listy bezpośrednio :

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

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

Tabele Lua są ściślejszymi odpowiednikami Python dictio raczej narkomani niż listy. Stworzona przez Ciebie tabela jest w istocie 1-indeksowaną tablicą ciągów. Użyj dowolnego standardowego algorytmu wyszukiwania, aby dowiedzieć się, czy wartość jest w tablicy. Innym podejściem byłoby przechowywanie wartości jako kluczy stołowych zamiast pokazanych w zestawie implementacji postu Jona Ericsona.

22

Użyj następujące reprezentacji Zamiast:

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

Jest to najlepszy sposób, aby zestaw (w czystej matematycznej sens) rzeczy w Lua. Brawo! Jednak ponieważ nie ma koncepcji zamówienia, nie musi odpowiadać na ogólne pytanie "Wyszukaj przedmiot na liście Lua?" jeśli kolejność list ma znaczenie. – Mark

+0

To jest o wiele bardziej eleganckie. Po prostu użył go do stworzenia tabeli, która wyglądała jak '{thingIAmLookingFor: true, secondThingIAmLookingFor: true}' –

+0

Nie wydaje się działać z liczbami. – CalculatorFeline

17

Ty widząc na własne oczy jedną z wad Lua posiadające tylko jedną strukturę danych --- trzeba toczyć własną rękę. Jeśli pozostaniesz z Luą, stopniowo będziesz gromadził bibliotekę funkcji, które manipulują tabelami w taki sposób, w jaki lubisz robić. Moja biblioteka obejmuje wymianę list-do-set i funkcja wyższego rzędu list-do wyboru:

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

To nie jest oszustwo posiadania jednej struktury danych, to tylko oszustwo Lua, które ma paskudną bibliotekę standardową. –

1

rodzaju rozwiązanie wykorzystujące 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 
+0

Jak to różni się od '' 'lokalnej workingtable = {} workingtable [123] = true workingtable [456] = true jeśli workingtable [456], a następnie ... 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 

oto funkcję używam do sprawdzania, czy dane znajdują się w tablicy.

1

Jest to funkcja swiss-armyknife można użyć:

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 

Można go używać do sprawdzenia, czy istnieje wartość:

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

Można używać go znaleźć klucz:

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

Mam nadzieję, że parametr recursive mówi sam za siebie.

Parametr metatables umożliwia także wyszukiwanie metatabeli.

Parametr keys powoduje, że funkcja szuka kluczy na liście. Oczywiście byłoby to bezużyteczne w Lua (można po prostu zrobić fruits[key]), ale wraz z recursive i metatables, staje się przydatny.

Parametr returnBool jest bezpieczne-guard, gdy masz tabele, które mają false jako klucz w tabeli (Tak, to możliwe: fruits = {false="apple"})

Powiązane problemy