最优雅的解决方案是使用 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
我正在学习 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