Reputation: 163
I'm learning Lua and coming from Python Lua tables seem rather convoluted, the simple example below is so elegant but translating this into Lua is difficult for me, as Lua has no concept of tuples.
So I'm looking for the best Lua solution for this snippet
a = [(1, 1), (2, 2), (3, 3), (4, 4)]
if (3, 3) in a:
print("Yay!")
else:
print("Nay!")
Upvotes: 1
Views: 502
Reputation: 1403
A pair is just like length-2 list, so you could express a
simply as
a = {{1, 1}, {2, 2}, {3, 3}, {4, 4}}
The tricky part here is rather that Python's in
compares objects by their value rather than their identity. That is, in Python, (1,2) in [(1,2)]
but (1,2) is not (1,2)
.
Lua has no notion of "value" equality (except for strings and numbers, which don't have identities).
You could override the behavior of ==
by setting the __eq
metametod. Unfortunately, Lua doesn't have a function for searching a table for a value equal to some query, so it might be overkill.
Directly, you could write a "contains pair" function that works on the a
as defined above like this:
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
You could make it more general by passing a function do the comparison (or equivalently, just use ==
but implement the __eq
metamethod):
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
If what you're really after is a set of pairs, you could instead use a "two-dimensional map" (a map of maps):
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
Checking that rows have already been created could be cumbersome. You can use metatables to imitate Python's defaultdict
and clean this up:
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
Upvotes: 2