最优雅的解决方案是使用 Lua 表来处理 Python 的这个片段

The most elegant solution using Lua tables to this snippet of Python

我正在学习 Lua 并且来自 Python Lua 表格看起来相当复杂,下面的简单示例非常优雅但是将其转换为 Lua 很难对我来说,因为 Lua 没有元组的概念。

所以我正在为这个片段寻找最好的Lua解决方案

a = [(1, 1), (2, 2), (3, 3), (4, 4)]
if (3, 3) in a:
    print("Yay!")
else:
    print("Nay!")

一对就像长度为 2 的列表,因此您可以将 a 简单地表示为

a = {{1, 1}, {2, 2}, {3, 3}, {4, 4}}

这里棘手的部分是 Python 的 in 通过对象的 value 而不是它们的 identity。也就是说,在 Python、(1,2) in [(1,2)](1,2) is not (1,2).

Lua 没有 "value" 相等的概念(字符串和数字除外,它们没有标识)。

您可以通过设置 __eq 元数据来覆盖 == 的行为。不幸的是,Lua 没有在 table 中搜索等于某个查询的值的功能,因此它可能有点矫枉过正。

直接地,您可以编写一个 "contains pair" 函数来处理上面定义的 a,如下所示:

function containsPair(list, pair)
    -- Find a key of list with a value equal to `pair` (as a pair)
    for k, v in ipairs(list) do
        if v[1] == pair[1] and v[2] == pair[2] then
            return k
        end
    end
end

if containsPair(a, {3, 3}) then
    ......
end

您可以通过传递一个函数来进行比较(或者等效地,只需使用 == 但实现 __eq 元方法):

function containsLike(list, lhs, eq)
    -- Find a key of list with a value equal to lhs
    for k, lhs in ipairs(list) do
        if eq(lhs, rhs) then
            return k
        end
    end
end

function pairEq(a, b)
    return a[1] == b[1] and a[2] == b[2]
end

if containsLike(list, {3, 3}, pairEq) then
    ......
end

如果您真正想要的是一组对,您可以改用"two-dimensional map"(地图中的地图):

a = {}
a[1] = {}
a[1][1] = true
a[2] = {}
a[2][2] = true
a[3] = {}
a[3][3] = true

if a[3] and a[3][3] then
    ......
end

检查行是否已创建可能很麻烦。您可以使用 metatables 来模仿 Python 的 defaultdict 并清理它:

function default(f)
    return setmetatable({}, {
        __index = function(self, k)
            -- self[k] is nil, but was asked for.
            -- Let's assign it to the default value:
            self[k] = f()

            -- and return the new assignment:
            return self[k]
        end,
    })
end

local a = default(function() return {} end)
a[1][1] = true
a[2][2] = true
a[3][3] = true

if a[3][3] then
    ......
end