Поиск предмета в списке Lua - PullRequest
46 голосов
/ 18 марта 2009

Если у меня есть список таких предметов:

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

как мне проверить, есть ли "оранжевый" в этом списке?

В Python я мог бы сделать:

if "orange" in items:
    # do something

Есть ли эквивалент в Lua?

Ответы [ 7 ]

71 голосов
/ 18 марта 2009

Вы можете использовать что-то вроде набора из Программирование на Lua :

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

Тогда вы можете поместить свой список в набор и проверить на членство:

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

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

Или вы можете перебирать список напрямую:

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

for _,v in pairs(items) do
  if v == "orange" then
    -- do something
    break
  end
end
25 голосов
/ 18 марта 2009

Вместо этого используйте следующее представление:

local items = { apple=true, orange=true, pear=true, banana=true }
if items.apple then
    ...
end
17 голосов
/ 20 марта 2009

Вы видите воочию один из минусов Lua, имеющий только одну структуру данных - вы должны свернуть свои собственные. Если вы придерживаетесь Lua, вы постепенно накапливаете библиотеку функций, которые управляют таблицами так, как вам нравится. Моя библиотека включает в себя преобразование из списка в набор и функцию поиска по списку более высокого порядка:

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
3 голосов
/ 18 марта 2009

Таблицы Lua являются более точными аналогами словарей Python, а не списками. Созданная вами таблица - это по существу индексированный массив строк на основе 1. Используйте любой стандартный алгоритм поиска, чтобы узнать, есть ли значение в массиве. Другой подход заключается в том, чтобы хранить значения в виде ключей таблицы, как показано в реализации набора записей Джона Эриксона.

2 голосов
/ 11 апреля 2014
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

Вот функция, которую я использую для проверки наличия данных в массиве.

1 голос
/ 20 октября 2016

Это функция швейцарского армейского ножа, которую вы можете использовать:

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

Вы можете использовать его, чтобы проверить, существует ли значение:

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

Вы можете использовать его, чтобы найти ключ:

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

Я надеюсь, что параметр recursive говорит сам за себя.

Параметр metatables также позволяет искать метатаблицы.

Параметр keys заставляет функцию искать ключи в списке. Конечно, это было бы бесполезно в Lua (вы можете просто сделать fruits[key]), но вместе с recursive и metatables это становится удобным.

Параметр returnBool обеспечивает надежную защиту, когда у вас есть таблицы, в которых ключом таблицы является false (да, это возможно: fruits = {false="apple"})

1 голос
/ 29 марта 2013

Сортировка по метатабельным решениям ...

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
...