126

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

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

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

4

5 回答 5

141

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

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

这里有一个功能更全面的例子。

于 2010-02-17T16:44:03.320 回答
26

鉴于您的代表,您的功能尽可能高效。 当然,正如其他人所指出的(以及在 Lua 之前的语言中所实践的),解决你真正问题的方法是改变表示。当您有表并且想要集合时,您可以通过使用集合元素作为键和true值将表转换为集合。+1 互助。

于 2010-02-17T17:17:06.690 回答
3

我知道这是一个旧帖子,但我想为后代添加一些东西。处理您遇到的问题的简单方法是制作另一个表,该表具有键值。

IE。您有 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 个副本。如果您的表非常小,那么它的重要性就会小得多,事实上,迭代甚至可能比另一个地图查找更快。

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

于 2013-09-02T09:15:40.810 回答
2

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

于 2010-02-17T16:43:37.563 回答
1
-- 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
于 2021-03-18T21:50:59.457 回答