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

发布于 2024-08-22 02:37:29 字数 306 浏览 9 评论 0原文

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

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

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

Is there a method for checking if a table contains a value ? I have my own (naive) function, but I was wondering if something "official" exists for that ? Or something more efficient...

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

By the way, the main reason I'm using this functions is to use tables as sets, ie with no duplicate elements. Is there something else I could use ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

终陌 2024-08-29 02:37:29

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

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

这里有一个功能更齐全的示例

You can put the values as the table's keys. For example:

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

There's a more fully-featured example here.

江南烟雨〆相思醉 2024-08-29 02:37:29

给定你的表示,你的函数是尽可能高效的。当然,正如其他人所指出的(以及早于 Lua 的语言中的实践),真正问题的解决方案是改变表示。当您有表并且需要集合时,可以通过使用 set 元素作为键并使用 true 作为值将表转换为集合。 +1 为 interjay。

Given your representation, your function is as efficient as can be done. Of course, as noted by others (and as practiced in languages older than Lua), the solution to your real problem is to change representation. When you have tables and you want sets, you turn tables into sets by using the set element as the key and true as the value. +1 to interjay.

落墨 2024-08-29 02:37:29

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

IE。您有两张具有相同值的表,一张指向一个方向,一张指向另一个方向。

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

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

I know this is an old post, but I wanted to add something for posterity.
The simple way of handling the issue that you have is to make another table, of value to key.

ie. you have 2 tables that have the same value, one pointing one direction, one pointing the other.

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

You can then query the new table to see if it has the key 'element'. This prevents the need to iterate through every value of the other table.

If it turns out that you can't actually use the 'element' as a key, because it's not a string for example, then add a checksum or tostring on it for example, and then use that as the key.

Why do you want to do this? If your tables are very large, the amount of time to iterate through every element will be significant, preventing you from doing it very often. The additional memory overhead will be relatively small, as it will be storing 2 pointers to the same object, rather than 2 copies of the same object.
If your tables are very small, then it will matter much less, infact it may even be faster to iterate than to have another map lookup.

The wording of the question however strongly suggests that you have a large number of items to deal with.

洒一地阳光 2024-08-29 02:37:29
-- 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
-- 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
逆夏时光 2024-08-29 02:37:29

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

I can't think of another way to compare values, but if you use the element of the set as the key, you can set the value to anything other than nil. Then you get fast lookups without having to search the entire table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文