Lua中的字符串是不可變的。這意味着,任何替換字符串中文本的解決方案必須最終構建一個具有所需內容的新字符串。對於使用其他內容替換單個字符的特定情況,您需要將原始字符串拆分爲前綴部分和後綴部分,然後將這些字符串連接在新內容周圍。
您的代碼這種變化:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
是最直接的翻譯直白的Lua。對於大多數目的而言,這可能足夠快。我已經修復了前綴應該是第一個字符的錯誤,並利用了這樣的事實:如果缺少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
有效連接字符串列表到最終的結果。它有一個可選的第二個參數,它是在字符串之間插入的文本,默認爲""
,這適合我們的目的。
我的猜測是,除非你的字符串很大,並且經常進行這種替換,否則這些方法之間不會有任何實際的性能差異。不過,我之前感到很驚訝,因此請通過簡要介紹您的應用程序來驗證是否存在瓶頸,並仔細地對潛在解決方案進行基準測試
感謝您的深入解釋 – dotminic
這是舊的。但我剛完成解決了我寫的一些代碼中的一個小錯誤。原來''replace_char2''方法不會插入空(''\ 0'')字符。 –
@DelusionalLogic好點。 'string.format'基於標準C的'sprintf()'函數,可能會遇到嵌入式NUL字節的問題。 – RBerteig