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