Поиск элемента в списке Lua
Если у меня есть список таких элементов:
local items = { "apple", "orange", "pear", "banana" }
как проверить, включен ли в этот список "оранжевый"?
В Python я мог бы сделать:
if "orange" in items:
# do something
Есть ли эквивалент в Lua?
Ответы
Ответ 1
Вы можете использовать что-то вроде набора из Программирование в Lua:
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
Затем вы можете поместить свой список в Set и test для членства:
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
Ответ 2
Вместо этого используйте следующее представление:
local items = { apple=true, orange=true, pear=true, banana=true }
if items.apple then
...
end
Ответ 3
Вы видите из первых рук один из недостатков 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
Ответ 4
Таблицы Lua более близки аналогам словарей Python, а не списков. Созданная вами таблица по существу представляет собой индексированный массив строк на основе 1. Используйте любой стандартный алгоритм поиска, чтобы узнать, находится ли значение в массиве. Другим подходом было бы сохранить значения в виде клавиш таблицы, как показано в заданной реализации сообщения Джона Эриксона.
Ответ 5
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
Здесь функция, которую я использую для проверки наличия данных в массиве.
Ответ 6
Сорт решения с использованием метатетируемого...
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
Ответ 7
Это функция swiss-armyknife, которую вы можете использовать:
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"}
)