Самое элегантное решение с использованием таблиц Lua для этого фрагмента Python - PullRequest
0 голосов
/ 14 мая 2018

Я изучаю 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 голосов
/ 15 мая 2018

Пара подобна списку длины-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 не имеет понятия о равенстве «значений» (за исключением строк и чисел, у которых нет тождеств).

Вы можете переопределить поведение ==, установив метаметод __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
...