list 在 Lua 列表中搜索项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/656199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:20:40  来源:igfitidea点击:

Search for an item in a Lua list

listlualua-table

提问by Jay

If I have a list of items like this:

如果我有这样的项目列表:

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

how do I check if "orange" is in this list?

如何检查“橙色”是否在此列表中?

In Python I could do:

在 Python 中,我可以这样做:

if "orange" in items:
    # do something

Is there an equivalent in Lua?

Lua中是否有等价物?

回答by Jon Ericson

You could use something like a set from Programming in Lua:

您可以使用来自Programming in Lua 中的 set 之类的东西:

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

Then you could put your list in the Set and test for membership:

然后您可以将您的列表放入 Set 并测试成员资格:

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

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

Or you could iterate over the list directly:

或者您可以直接遍历列表:

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

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

回答by Jay

Use the following representation instead:

请改用以下表示:

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

回答by Norman Ramsey

You're seeing firsthand one of the cons of Lua having only one data structure---you have to roll your own. If you stick with Lua you will gradually accumulate a library of functions that manipulate tables in the way you like to do things. My library includes a list-to-set conversion and a higher-order list-searching function:

您亲眼目睹了 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

回答by Judge Maygarden

Lua tables are more closely analogs of Python dictionaries rather than lists. The table you have create is essentially a 1-based indexed array of strings. Use any standard search algorithm to find out if a value is in the array. Another approach would be to store the values as table keys instead as shown in the set implementation of Jon Ericson's post.

Lua 表更接近于 Python 字典而不是列表。您创建的表本质上是一个基于 1 的索引字符串数组。使用任何标准搜索算法来确定某个值是否在数组中。另一种方法是将值存储为表键,而不是如 Jon Ericson 帖子的集合实现中所示。

回答by 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

Here's the function I use for checking if data is in an array.

这是我用于检查数据是否在数组中的函数。

回答by Luc Bloom

This is a swiss-armyknife function you can use:

这是您可以使用的 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

You can use it to check if a value exists:

您可以使用它来检查值是否存在:

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

You can use it to find the key:

您可以使用它来查找密钥:

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

I hope the recursiveparameter speaks for itself.

我希望recursive参数不言自明。

The metatablesparameter allows you to search metatables as well.

metatables参数还允许您搜索元表。

The keysparameter makes the function look for keys in the list. Of course that would be useless in Lua (you can just do fruits[key]) but together with recursiveand metatables, it becomes handy.

keys参数使函数在列表中查找键。当然,这在 Lua 中是没用的(你可以直接做fruits[key]),但是与recursive和一起metatables,它变得很方便。

The returnBoolparameter is a safe-guard for when you have tables that have falseas a key in a table (Yes that's possible: fruits = {false="apple"})

returnBool参数是一个安全守卫,因为当你有一个有表false为表中的一个键(是的,这是可能的:fruits = {false="apple"}

回答by Konstantin Artemiev

Sort of solution using 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