string - 在Lua中修改字符串中的字符

标签 string lua gsub lua-patterns

有什么办法可以替换Lua中字符串N处的字符。

到目前为止,这是我想出的:

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位的捕获。

最佳答案

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,它等于字符串的结尾。

但是请注意,它会创建许多临时字符串,这些临时字符串会在字符串存储区中徘徊,直到垃圾回收吞噬它们为止。在任何解决方案中都无法避免使用前缀和后缀。但这还必须为第一个..运算符创建一个临时值,以供第二个运算符使用。

两种替代方法之一可能会更快。第一个是solution offered by 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首次出现时终止替换的字符串。 (由Delusional Logic用户在注释中注明。)

我想到的第三个选择是:
function replace_char3(pos, str, r)
    return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat有效地将字符串列表连接到最终结果中。它有一个可选的第二个参数,即要在字符串之间插入的文本,默认为"",适合我们的目的。

我的猜测是,除非您的字符串很大并且您经常进行此替换,否则这些方法之间不会发现任何实际的性能差异。但是,我之前感到很惊讶,因此对您的应用程序进行概要分析以验证是否存在瓶颈,并仔细基准化潜在的解决方案。

关于string - 在Lua中修改字符串中的字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5249629/

相关文章:

string - 替换包含特定字符串的整个表达式

c++ - 是否可以为 C++ +'s string class? And to concatenate "文字创建运算符函数?

c++ - 链接器错误 Lua 5.1

c# - StringBuilder内存不足

Lua字符串转int

lua - 使用 Wifi 将 Lua 脚本上传到 NodeMCU

regex - 如何在 r 中重新排序和替换字符串的一部分?

在 R 中同时将 "1"替换为 "0",将 "0"替换为 "1"

Javascript String.fromCharCode 区分大小写吗?

使用 calloc 将十进制数组转换为二进制字符串数组