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

发布于 2024-10-21 05:32:17 字数 284 浏览 7 评论 0原文

有什么办法可以替换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 处的捕获。

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)

I can't use gsub either as that would replace every capture, not just the capture at position N.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

痴情换悲伤 2024-10-28 05:32:17

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 可能会对通过 %s 格式传递的任何字符串中的任何 \0 字符产生问题。具体来说,由于它是根据标准 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 有效地将字符串列表连接成最终结果。它有一个可选的第二个参数,它是要在字符串之间插入的文本,默认为 "" ,这适合我们在这里的目的。

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

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.

This variation on your code:

function replace_char(pos, str, r)
    return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end

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.

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

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.

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.)

A third alternative that comes to mind is this:

function replace_char3(pos, str, r)
    return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end

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.

烟雨凡馨 2024-10-28 05:32:17

您应该在函数内使用 pos 而不是文字 13,但除此之外它看起来不错。由于 Lua 字符串是不可变的,你真的不能做得比这更好了。

Maybe

 "%s%s%s":format(str:sub(1,pos-1), r, str:sub(pos+1, str:len())

.. 运算符更有效,但我对此表示怀疑 - 如果结果证明它是瓶颈,请对其进行测量(然后决定在 C 中实现此替换函数)。

You should use pos inside your function instead of literal 1 and 3, but apart from this it looks good. Since Lua strings are immutable you can't really do much better than this.

Maybe

 "%s%s%s":format(str:sub(1,pos-1), r, str:sub(pos+1, str:len())

is more efficient than the .. operator, but I doubt it - if it turns out to be a bottleneck, measure it (and then decide to implement this replacement function in C).

放肆 2024-10-28 05:32:17

通过 luajit,您可以使用 FFI 库将字符串转换为无符号图表列表:

local ffi = require 'ffi'
txt = 'test'
ptr = ffi.cast('uint8_t*', txt)
ptr[1] = string.byte('o')

With luajit, you can use the FFI library to cast the string to a list of unsigned charts:

local ffi = require 'ffi'
txt = 'test'
ptr = ffi.cast('uint8_t*', txt)
ptr[1] = string.byte('o')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文