Căutarea unui element într-o listă Lua (Programare, Lista, Lua, Tabel Lua)

Jay a intrebat.

Dacă am o listă de elemente ca aceasta:

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

cum pot verifica dacă „portocaliu” este în această listă?

În Python aș putea face:

if "orange" in items:
    # do something

Există un echivalent în Lua?

10 răspunsuri
Jon Ericson

Ați putea folosi ceva de genul unui set din Programarea în Lua:

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

Apoi ai putea să pui lista ta în Set și să testezi apartenența:

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

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

Sau ai putea itera direct peste listă:

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

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

fsanbr

Utilizați în schimb următoarea reprezentare:

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

Comentarii

  • Acesta este cel mai bun mod de a crea un set (în sens pur matematic) de lucruri în Lua. Bravo! Cu toate acestea, deoarece nu are un concept de ordine, nu răspunde neapărat la întrebarea generală „Căutați un element într-o listă Lua?” dacă ordinea listei contează. –  > Por Mark.
  • Acest lucru pare mult mai elegant. Tocmai am folosit-o pentru a crea un tabel care arăta astfel {thingIAmLookingFor:true, secondThingIAmLookingFor:true} –  > Por stiller_leser.
  • Acesta este un răspuns frumos, dar nu abordează problema generală a întrebării: ce se întâmplă cu o listă arbitrară de șiruri de caractere? Echivalentul if "orange" in items din Python nu necesită construirea unei liste specializate proprii. Există o modalitate Lua de a lua orice listă de șiruri de caractere și de a o reconstrui în acest mod? –  > Por Zim.
  • @CalculatorFeline Unele chei (care au numere, spații, accente…) au nevoie de notația de paranteze. de ex: local items = { [42]=true, ['foo bar']=true, ['éà']=true }. De fapt, notația fără paranteze este un zahăr sintaxic (ca de multe ori în Lua). S-ar putea să vă intereseze Tutorial de tabele. –  > Por Gras Double.
Norman Ramsey

Vedeți pe propria piele unul dintre dezavantajele faptului că Lua are o singură structură de date – trebuie să vă creați propria structură. Dacă rămâi cu Lua, vei acumula treptat o bibliotecă de funcții care manipulează tabelele în modul în care îți place să faci lucrurile. Biblioteca mea include o conversie de la listă la set și o funcție de căutare a listei de ordin superior:

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

Judecătorul Maygarden

Tabelele Lua sunt mai degrabă analogii cu dicționarele Python decât cu listele. Tabelul pe care l-ați creat este, în esență, o matrice de șiruri de caractere indexate pe baza 1. Utilizați orice algoritm standard de căutare pentru a afla dacă o valoare se află în tablou. O altă abordare ar fi să stocați valorile ca chei de tabel, așa cum se arată în implementarea setului din postarea lui Jon Ericson.

Luc Bloom

Aceasta este o funcție swiss-armyknife pe care o puteți utiliza:

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

Puteți să o utilizați pentru a verifica dacă o valoare există:

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

O puteți utiliza pentru a găsi cheia:

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

Sper că recursive parametrul vorbește de la sine.

metatables vă permite, de asemenea, să căutați în metatablete.

keys face ca funcția să caute chei în listă. Desigur, acest lucru ar fi inutil în Lua (puteți face doar fruits[key]), dar împreună cu recursive și metatables, , devine util.

Adresa returnBool este o măsură de siguranță pentru cazurile în care aveți tabele care au false ca o cheie într-un tabel (Da, este posibil: fruits = {false="apple"})

KingofGamesYami
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

Iată funcția pe care o folosesc pentru a verifica dacă datele se află într-un array.

Konstantin Artemiev

Un fel de soluție folosind 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

Comentarii

  • Care este diferența față de local workingtable={} workingtable[123] = true workingtable[456] = true if workingtable[456] then ... end –  > Por Luc Bloom.
nxFairlywell
function table.find(t,value)
    if t and type(t)=="table" and value then
        for _, v in ipairs (t) do
            if v == value then
                return true;
            end
        end
        return false;
    end
    return false;
end

Comentarii

  • Deși acest cod ar putea rezolva problema, un răspuns bun ar trebui să explice și ce este face codul și cum ajută. –  > Por BDL.
Setareh Nazeri

puteți folosi această soluție:

items = { 'a', 'b' }
for k,v in pairs(items) do 
 if v == 'a' then 
  --do something
 else 
  --do something
 end
end

sau

items = {'a', 'b'}
for k,v in pairs(items) do 
  while v do
    if v == 'a' then 
      return found
    else 
      break
    end
  end 
 end 
return nothing

Doyousketch2

Scrieți-l oricum doriți, dar este mai rapid să iterați direct peste listă, , decât să generați perechi() sau iperechi()

#! /usr/bin/env lua

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

local function locate( table, value )
    for i = 1, #table do
        if table[i] == value then print( value ..' found' ) return true end
    end
    print( value ..' not found' ) return false
end

locate( items, 'orange' )
locate( items, 'car' )

portocaliu găsit
mașină nu a fost găsită