Lua: подставить список символов в строку

Можно ли заменять символы согласно списку в Lua, например tr в Perl? Например, я хотел бы заменить A на B и B на A (например, AABBCC становится BBAACC).

В Perl решением будет $str ~= tr/AB/BA/. Есть ли какой-нибудь собственный способ сделать это в Lua? В противном случае я думаю, что лучшим решением будет итерация по всей строке, поскольку при отдельных заменах необходимо использовать специальный символ, чтобы различать символы, которые уже были заменены, и символы, которые не были.

Изменить: моей целью было вычислить обратное дополнение строки ДНК, как описано здесь < / а>.


person Fábio Perez    schedule 05.11.2013    source источник


Ответы (2)


string.gsub может принимать таблицу в качестве третьего аргумента. Таблица запрашивается для каждого совпадения с использованием первого захвата в качестве ключа, а связанное значение используется в качестве строки замены. Если значение равно nil, совпадение не изменяется.

Итак, вы можете создать вспомогательную таблицу следующим образом:

local s = "AABBCC"
local t = {A = "B", B = "A"}
local result = string.gsub(s, "[AB]", t)
print(result)

или тот же однострочный:

print((string.gsub("AABBCC", "[AB]", {A = "B", B = "A"})))

Вывод:

BBAACC

Для односимвольного шаблона, такого как "[AB]", "." также может работать, потому что все, что не найдено в таблице, не будет изменено. (Но я не думаю, что это более эффективно) Но для некоторых более сложных случаев нужен хороший шаблон.

Вот пример из Программирование на Lua: эта функция заменяет значение глобальной переменной varname для каждого появления $varname в строке:

function expand (s)
    return (string.gsub(s, "$(%w+)", _G))
end
person Yu Hao    schedule 05.11.2013
comment
+1 Я не знал о табличной форме gsub. Намного лучше, чем метод функции, который я использовал. - person HennyH; 05.11.2013
comment
Отличное решение! Как вы думаете, будет ли эффективнее заменить "[A|B]" на "." (соответствие каждого символа)? Я проверил, и результат такой же. - person Fábio Perez; 05.11.2013
comment
@ FábioPerez Да. \ @YuHao lua-шаблоны не поддерживают соответствие |, например регулярное выражение. Кроме того, [AB] тоже подойдет. - person hjpotter92; 05.11.2013

Приведенный ниже код заменит каждый символ желаемым отображением (или оставьте его в покое, если отображение не существует). Вы можете изменить второй параметр на string.gsub в tr, чтобы быть более конкретным, если вы знаете точный диапазон символов.

s = "AABBCC"
mappings = {["A"]="B",["B"]="A"}

function tr(s,mappings)
    return string.gsub(s,
        "(.)",
        function(m)
            -- print("found",m,"replace with",mappings[m],mappings[m] or m)
            if mappings[m] == nil then return m else return mappings[m] end
        end 
    )
end

print(tr(s,mappings))

Выходы

henry@henry-pc:~/Desktop$ lua replace.lua
found   A   replace with    B   B
found   A   replace with    B   B
found   B   replace with    A   A
found   B   replace with    A   A
found   C   replace with    nil C
found   C   replace with    nil C
BBAACC  6
person HennyH    schedule 05.11.2013