Строки в Lua неизменяемы. Это означает, что любое решение, заменяющее текст в строке, должно привести к созданию новой строки с желаемым содержимым. В конкретном случае замены одного символа каким-либо другим содержимым вам потребуется разбить исходную строку на часть префикса и часть постфикса и соединить их вместе вокруг нового содержимого.
Этот вариант вашего кода:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
это самый прямой перевод на простой Lua. Это, вероятно, достаточно быстро для большинства целей. Я исправил ошибку, из-за которой префикс должен быть первым символом pos-1
, и воспользовался тем фактом, что если последний аргумент string.sub
отсутствует, предполагается, что он равен -1
, что эквивалентно концу строки.
Но обратите внимание, что он создает ряд временных строк, которые будут висеть в хранилище строк, пока их не съест сборка мусора. Временных для префикса и постфикса нельзя избежать ни в одном решении. Но это также должно создать временный объект для первого оператора ..
, который будет использоваться вторым.
Возможно, что один из двух альтернативных подходов может быть быстрее. Первое — это решение, предложенное Пауло Эберманном, но с одной небольшой поправкой:
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
могут быть проблемы с любыми \0
символами в любой строке, которую он передает через формат %s
. В частности, поскольку она реализована в терминах стандартной функции C sprintf()
, было бы разумно ожидать, что она завершит замещаемую строку при первом появлении \0
. (Отмечено пользователем Delusional Logic в комментарии.)
Третий вариант, который приходит на ум, заключается в следующем:
function replace_char3(pos, str, r)
return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat
эффективно объединяет список строк в окончательный результат. У него есть необязательный второй аргумент, который представляет собой текст для вставки между строками, который по умолчанию равен ""
, что подходит для нашей цели.
Я предполагаю, что если ваши строки не огромны и вы часто выполняете эту замену, вы не увидите никаких практических различий в производительности между этими методами. Однако я был удивлен ранее, поэтому профилируйте свое приложение, чтобы убедиться в наличии узкого места, и тщательно сравните потенциальные решения.
person
RBerteig
schedule
10.03.2011