如何检查表是不是包含Lua中的元素?

Posted

技术标签:

【中文标题】如何检查表是不是包含Lua中的元素?【英文标题】:How to check if a table contains an element in Lua?如何检查表是否包含Lua中的元素? 【发布时间】:2011-01-17 22:54:32 【问题描述】:

有没有一种方法可以检查一个表是否包含一个值?我有自己的(天真的)功能,但我想知道是否存在“官方”的东西?或者更高效的方法...

function table.contains(table, element)
  for _, value in pairs(table) do
    if value == element then
      return true
    end
  end
  return false
end

顺便说一句,我使用这个函数的主要原因是使用表格作为集合,即没有重复的元素。还有什么我可以用的吗?

【问题讨论】:

_,符号是什么意思? 这只是一个名为_ 的“垃圾”变量。 pairs() 返回key, value,但在这个例子中我只需要这个值。这是一种约定(在“Lua 编程”lua.org/pil/index.html 一书中采用)使用这个_ 变量来存储你不需要的东西。 我在 Python 和 javascript 中也看到了命名“垃圾”变量_ 的约定。 【参考方案1】:

您可以将值作为表的键。例如:

function addToSet(set, key)
    set[key] = true
end

function removeFromSet(set, key)
    set[key] = nil
end

function setContains(set, key)
    return set[key] ~= nil
end

还有一个功能更全面的例子here。

【讨论】:

一位匿名用户建议对您的代码进行以下修复:如果具有指定键的集合中的值为 FALSE,则函数 setContains() 将返回 false,尽管表中有一个项目具有指定的键。 “return set[key] ~= nil”这一行修复了这个错误。 也许还有function keysOfSet(set) local ret= for k,_ in pairs(set) do ret[#ret+1]=k end return ret end【参考方案2】:

鉴于您的表述,您的功能已尽其所能。当然,正如其他人所指出的(以及在 Lua 之前的语言中所实践的),您真正问题的解决方案是改变表示。当您有表格并且想要集合时,您可以使用 set 元素作为键并使用 true 作为值将表格转换为集合。 +1 给 interjay。

【讨论】:

“官方”方法可能会在 C 中执行此操作,这样会更快。但如果只在 lua 中完成,如你所说,这是可能的最有效的方法!【参考方案3】:

我知道这是一篇旧帖子,但我想为后代添加一些内容。 处理您遇到的问题的简单方法是创建另一个表,对键值。

即。您有 2 个具有相同值的表,一个指向一个方向,一个指向另一个。

function addValue(key, value)
    if (value == nil) then
        removeKey(key)
        return
    end
    _primaryTable[key] = value
    _secodaryTable[value] = key
end

function removeKey(key)
    local value = _primaryTable[key]
    if (value == nil) then
        return
    end
    _primaryTable[key] = nil
    _secondaryTable[value] = nil
end

function getValue(key)
    return _primaryTable[key]
end

function containsValue(value)
    return _secondaryTable[value] ~= nil
end

然后您可以查询新表以查看它是否具有键“元素”。这避免了遍历另一个表的每个值的需要。

如果事实证明您实际上不能将“元素”用作键,例如因为它不是字符串,那么例如在其上添加校验和或tostring,然后将其用作键.

为什么要这样做?如果您的表非常大,则遍历每个元素的时间会很长,从而使您无法经常这样做。额外的内存开销相对较小,因为它将存储 2 个指向同一个对象的指针,而不是同一个对象的 2 个副本。 如果您的表非常小,那么它的影响会小得多,事实上,迭代甚至可能比另一个地图查找更快。

然而,问题的措辞强烈暗示您有大量的项目需要处理。

【讨论】:

一个很好的解释,但并没有真正为讨论添加任何内容。编辑 interjay 的答案可能是一个更好的主意。 另外,在这段代码中,'.key' 应替换为 '[key]'(与 'value' 相同)【参考方案4】:

我想不出另一种比较值的方法,但是如果您使用集合的元素作为键,您可以将值设置为 nil 以外的任何值。然后您无需搜索整个表即可快速查找。

【讨论】:

【参考方案5】:
-- in some helper module
function utils_Set(list)
    local set = 
    for _, l in ipairs(list) do set[l] = true end
    return set
end

-- your table here
long_table =  "v1", "v2", "v1000"

-- Consult some value
_set = utils_Set(long_table)
if _set["v1"] then print("yes!") end

【讨论】:

喜欢这个是因为不需要经常维护并行表。

以上是关于如何检查表是不是包含Lua中的元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查Lua中的值是不是为空?

Lua:如何检查字符串是不是只包含数字和字母?

如何检查 Lua 中是不是存在模块?

如何检查字符串是不是包含数组中的任何元素[关闭]

如何检查元组是不是包含 Apache Pig 中的元素?

在 Presto 中,如何检查我通过子查询获取的列表中是不是存在数组中的元素