Изменение символа в строке в Lua
есть ли способ заменить символ в позиции N в строке в Lua.
вот что я придумал до сих пор:
function replace_char(pos, str, r)
return str:sub(pos, pos - 1) .. r .. str:sub(pos + 1, str:len())
end
str = replace_char(2, "aaaaaa", "X")
print(str)
Я не могу использовать gsub, так как это заменит каждый захват, а не только захват в позиции N.
3 ответов
строки в Lua неизменяемы. Это означает, что любое решение, которое заменяет текст в строке, должно в конечном итоге создать новую строку с требуемым содержимым. Для конкретного случая замены одного символа другим содержимым вам нужно будет разделить исходную строку на префиксную часть и постфиксную часть и объединить их вокруг нового содержимого.
эта вариация вашего кода:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
это самый прямой перевод простой Lua. Вероятно, это достаточно быстро для большинства целей. Я исправил ошибку, что префикс должен быть первым pos-1
chars, и воспользовался тем, что если последний аргумент string.sub
отсутствует, предполагается, что -1
что эквивалентно концу строки.
но обратите внимание, что он создает ряд временных строк, которые будут висеть в хранилище строк, пока сборщик мусора не съест их. Временные для префикса и постфикса не могут избегайте в любом решении. Но это также должно создать временное для первого ..
оператор, который будет потребляться вторым.
вполне возможно, что один из двух альтернативных подходов может быть быстрее. Первый-это решение, предлагаемое Paŭlo Ebermann, но с одной небольшой твик:
function replace_char2(pos, str, r)
return ("%s%s%s"):format(str:sub(1,pos-1), r, str:sub(pos+1))
end
использует string.format
сделать сборку результата в надежде, что он может угадать окончательный размер буфера без необходимости дополнительных временных объектов.
но остерегайтесь этого string.format
вероятно, будут проблемы с любым символы в любой строке, которая проходит через его . В частности, поскольку он реализован в терминах стандарта C
sprintf()
функция, было бы разумно ожидать, что она завершит замещенную строку при первом появлении . (Отмечено пользователем Бредовая Логика в комментарии.)
третья альтернатива, которая приходит на ум это:
function replace_char3(pos, str, r)
return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat
эффективно объединяет список строк в конечный результат. Он имеет необязательный второй аргумент, который является текстом для вставки между строками, который по умолчанию равен ""
что соответствует нашей цели здесь.
Я предполагаю, что если ваши строки не огромны, и вы часто делаете эту замену, вы не увидите никаких практических различий в производительности между этими методами. Тем не менее, я был удивлен раньше, поэтому профилируйте свое приложение проверьте наличие узкого места и тщательно проверьте потенциальные решения.
вы должны использовать pos
внутри вашей функции вместо literal 1
и 3
, но кроме этого он выглядит хорошо. Поскольку строки Lua неизменяемы, вы не можете сделать намного лучше, чем это.
может быть
"%s%s%s":format(str:sub(1,pos-1), r, str:sub(pos+1, str:len())
более эффективно, чем ..
оператор, но я сомневаюсь в этом - если это окажется узким местом, измерьте его (а затем решите реализовать эту функцию замены в C).
С luajit вы можете использовать библиотеку FFI для приведения строки в список неподписанных диаграмм:
local ffi = require 'ffi'
txt = 'test'
ptr = ffi.cast('uint8_t*', txt)
ptr[1] = string.byte('o')