问题描述
有没有办法替换Lua中字符串N处的字符.
Is there any way to replace a character at position N in a string in Lua.
这是我到目前为止提出的:
This is what I've come up with so far:
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位的捕获.
I can't use gsub either as that would replace every capture, not just the capture at position N.
推荐答案
Lua中的字符串是不可变的.这意味着,任何替换字符串中文本的解决方案都必须最终构造具有所需内容的新字符串.对于用其他内容替换单个字符的特定情况,您将需要将原始字符串拆分为前缀部分和后缀部分,然后将它们围绕新内容重新连接在一起.
Strings in Lua are immutable. That means, that any solution that replaces text in a string must end up constructing a new string with the desired content. For the specific case of replacing a single character with some other content, you will need to split the original string into a prefix part and a postfix part, and concatenate them back together around the new content.
您的代码的这种变化:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
是对直接Lua的最直接的翻译.对于大多数用途而言,它可能足够快.我已经修复了前缀应为第一个pos-1
字符的错误,并利用了以下事实:如果缺少string.sub
的最后一个参数,则假定它是-1
,它等同于-1
的结尾.字符串.
is the most direct translation to straightforward Lua. It is probably fast enough for most purposes. I've fixed the bug that the prefix should be the first pos-1
chars, and taken advantage of the fact that if the last argument to string.sub
is missing it is assumed to be -1
which is equivalent to the end of the string.
但是请注意,它会创建许多临时字符串,这些临时字符串会在字符串存储中徘徊,直到垃圾回收吞噬它们为止.在任何解决方案中都无法避免使用前缀和后缀.但这还必须为第一个..
运算符创建一个临时值,以供第二个..
运算符使用.
But do note that it creates a number of temporary strings that will hang around in the string store until garbage collection eats them. The temporaries for the prefix and postfix can't be avoided in any solution. But this also has to create a temporary for the first ..
operator to be consumed by the second.
两种替代方法之一可能更快.第一个是PaŭloEbermann提供的解决方案,但有一个小的调整:
It is possible that one of two alternate approaches could be faster. The first is the solution offered by Paŭlo Ebermann, but with one small tweak:
function replace_char2(pos, str, r)
return ("%s%s%s"):format(str:sub(1,pos-1), r, str:sub(pos+1))
end
这使用string.format
进行结果的汇编,希望它可以猜测最终的缓冲区大小而无需额外的临时对象.
This uses string.format
to do the assembly of the result in the hopes that it can guess the final buffer size without needing extra temporary objects.
但是请注意,string.format
可能会通过%s
格式传递的任何字符串中的任何\0
字符都有问题.具体来说,由于它是根据标准C的sprintf()
函数实现的,因此可以合理地期望它在第一次出现\0
时终止替换的字符串. (在注释中由用户 Delusional Logic 注意到.)
But do beware that string.format
is likely to have issues with any \0
characters in any string that it passes through its %s
format. Specifically, since it is implemented in terms of standard C's sprintf()
function, it would be reasonable to expect it to terminate the substituted string at the first occurrence of \0
. (Noted by user Delusional Logic in a comment.)
想到的第三个选择是:
function replace_char3(pos, str, r)
return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat
有效地将字符串列表连接成最终结果.它有一个可选的第二个参数,即要在字符串之间插入的文本,默认为""
,这符合我们的目的.
table.concat
efficiently concatenates a list of strings into a final result. It has an optional second argument which is text to insert between the strings, which defaults to ""
which suits our purpose here.
我的猜测是,除非您的字符串很大且您经常进行此替换,否则这些方法之间不会发现任何实际的性能差异.但是,我之前很惊讶,因此对您的应用程序进行概要分析以验证是否存在瓶颈,并仔细基准化潜在的解决方案.
My guess is that unless your strings are huge and you do this substitution frequently, you won't see any practical performance differences between these methods. However, I've been surprised before, so profile your application to verify there is a bottleneck, and benchmark potential solutions carefully.
这篇关于在Lua中修改字符串中的字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!