
順番
〜文字列の部分一致と置換の順序に注意〜
はじめに
Pythonでリストの中の文字列を一部だけ置き換えたいとき、
replace()メソッドを使うのが一般的です。
xxxx-AB1
もあればxxxx-AB1D
もある場合
どう書けばいいのか?
基本的な置換:-AB1を削除したい
たとえば、次のようなリストがあるとします:
lists = ["1234-AB1", "5678-AB1", "9999-XY1"]
-AB1
を削除したい場合は、replace()を使って以下のように書けます:
lists = [part.replace("-AB1", "") for part in lists]
結果はこうなります:
["1234", "5678", "9999-XY1"]
これは期待通りの動作です。
想定外の結果になるケース:-AB1Dを含む場合
次のようなデータを処理したい場合はどうでしょうか?
lists = ["1234-AB1D", "5678-AB1D", "9999-XY1"]
ここでも replace("-AB1", "")
を使ってみると:
["1234D", "5678D", "9999-XY1"]
一見うまくいったように見えますが、
実は「-AB1D」が「-AB1」だけ削除されたため、"D" が残ってしまっている
なぜそうなるのか?
.replace("-AB1", "") は、文字列の中の "-AB1" の部分だけを 完全一致で削除 します。
それ以外の部分(例えば D)は残ります。
"1234-AB1D" → "1234D"("-AB1" が削除され、"D" は残る)
"5678-AB1D" → "5678D"
"9999-XY1" → 変化なし("-AB1" が含まれていないため)
解決方法:長い文字列から先に置換する
このような場合は、より長い文字列(-AB1D
)から先に置換するのが正しい順番です。
lists = ["1234-AB1", "5678-AB1", "9999-XY1", "9999-AB1D"]
lists = [part.replace("-AB1D", "").replace("-AB1", "") for part in lists]
こうすることで、正しく以下の結果が得られます:
["1234", "5678", "9999-XY1", "9999"]
おわりに
文字列の置換処理はシンプルなようで、
順番や対象によって結果が変わってしまうこともあります。
今回のように、
部分的に重なった文字列を処理する場合は、長い方から先に置換する