8

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)

位置Nのキャプチャだけでなく、すべてのキャプチャを置き換えるため、gsubも使用できません。

4

3 に答える 3

14

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、文字列の終わりと同等であると見なされるという事実を利用しました。

ただし、ガベージコレクションがそれらを食い尽くすまで文字列ストアでぶらぶらする一時的な文字列がいくつか作成されることに注意してください。プレフィックスとポストフィックスの一時的なものは、どのソリューションでも回避できません。ただし、これは、最初の..オペレーターが2番目のオペレーターによって消費される一時的なものも作成する必要があります。

2つの代替アプローチのいずれかがより高速である可能性があります。1つ目は、PaŭloEbermannが提供するソリューションですが、わずかな調整が1つあります。

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問題が発生する可能性があることに注意してください。具体的には、標準Cの関数で実装されているため、。の最初の出現時に置換された文字列を終了することを期待するのが妥当です。(コメントの中でユーザーの妄想論理によって指摘されています。)\0%ssprintf()\0

頭に浮かぶ3番目の選択肢はこれです:

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

table.concat文字列のリストを効率的に連結して最終結果にします。これには、文字列の間に挿入するテキストであるオプションの2番目の引数があります。これは、デフォルトで、""ここでの目的に適しています。

私の推測では、文字列が巨大で、この置換を頻繁に行わない限り、これらのメソッド間で実際のパフォーマンスの違いは見られません。ただし、以前は驚いたことがあるので、アプリケーションのプロファイルを作成してボトルネックがあることを確認し、潜在的なソリューションを慎重にベンチマークします。

于 2011-03-10T20:10:25.190 に答える
5

posリテラル1との代わりに関数内で使用する必要があります3が、これを除けば見栄えがします。Luaの文字列は不変であるため、これよりもはるかに優れた方法はありません。

多分

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

はオペレーターよりも効率的です..が、私はそれを疑っています-それがボトルネックであることが判明した場合は、それを測定します(そして、この置換関数をCで実装することを決定します)。

于 2011-03-09T18:16:25.093 に答える