使用Lua表到这个Python片段的最优雅的解决方案

时间:2018-05-14 19:02:02

标签: lua lua-table

我学习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!")

1 个答案:

答案 0 :(得分:2)

一对就像长度为2的列表一样,所以你可以简单地将a表示为

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

这里棘手的部分是Python in通过而不是身份来比较对象。也就是说,在Python中,(1,2) in [(1,2)]只有(1,2) is not (1,2)

Lua没有"价值"平等(字符串和数字除外,它们没有身份)。

您可以通过设置== metametod来覆盖__eq的行为。遗憾的是,Lua没有搜索表等于某个查询值的函数,因此它可能有点过分。

直接地,你可以写一个"包含对"适用于上面定义的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

如果您真正关注的是一组,您可以使用"二维地图" (地图):

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

检查是否已创建行可能很麻烦。您可以使用元表来模仿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