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

是否有检查表是否包含值的方法?我有我自己的(天真的)功能,但我想知道是否有“官方”的存在?或者更有效率的方法。

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

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

236383 次浏览

我想不出其他比较值的方法,但是如果您使用 set 的元素作为键,那么您可以将值设置为 nil 以外的任何值。然后您可以快速查找,而不必搜索整个表。

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

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

还有一个功能更全面的例子 给你

考虑到您的表示,你的功能已经尽可能的高效了。当然,正如其他人所指出的(并且在比 Lua 更古老的语言中实践过) ,您真正问题的解决方案是更改表示。当您有表并需要集合时,可以通过使用 set 元素作为键和 true作为值来将表转换为集合。中场休息加1分。

我知道这是一个老职位,但我想增加一些后代。 处理这个问题的简单方法是创建另一个值对键的表。

也就是说,有两个值相同的表,一个指向一个方向,一个指向另一个方向。

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

然后可以查询新表,看看它是否具有键“ element”。这可以防止需要迭代另一个表的每个值。

如果实际上你不能使用“元素”作为键,因为它不是一个字符串,那么添加一个校验和或者 tostring,然后使用它作为键。

你为什么要这么做?如果您的表非常大,那么遍历每个元素所需的时间将非常长,从而使您无法经常这样做。额外的内存开销将相对较小,因为它将存储指向同一对象的2个指针,而不是同一对象的2个副本。 如果您的表非常小,那么它的重要性就会小得多,实际上迭代可能比使用另一个映射查找更快。

这个问题的措辞无论多么强烈地暗示你有大量的事情要处理。

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