閉じる

str.translateで複数文字を一括置換する方法とreplaceの違い

複数の文字を一括で置換・削除したいとき、Pythonのstr.translateは非常に強力です。

1回の走査で多くの文字を同時に扱えるため、順序に依存せず高速に正規化ができます

本記事ではstr.maketransで作る置換マップの基本から、replacere.subとの使い分け、実用的な例まで初心者向けに丁寧に解説します。

str.translateの基本(複数文字を一括置換)

複数の文字を同時に置換・削除できる

同時置換のイメージ

str.translate「文字ごと」にマッピング表(変換テーブル)を参照して、各文字を置換または削除します。

トランスレーションテーブルはstr.maketransで作ります。

基本的な呼び出し方

次の例では、A@B8に置換し、ハイフン-は削除します。

Python
# 基本: 同時に複数置換+削除
s = "ABC-123-XYZ"

# dictで置換マップを記述。削除は None を指定します。
table = str.maketrans({
    "A": "@",
    "B": "8",
    "-": None,  # ハイフンは削除
})

result = s.translate(table)
print(result)
実行結果
@8C123XYZ

ポイントとして、1回の処理で全部の文字に対して同時に適用されるので、先にAを置換してからB…という順序を考える必要がありません。

置換は1文字単位で部分文字列は不可

部分文字列(長さ2以上)はキーにできない

注意として、translateは「1文字単位」の置換しかできません

例えば"th"を一度に"X"へ置換する、といった「部分文字列」置換は不可です。

Python
# 部分文字列の置換を試みる(誤りの例)
try:
    table = str.maketrans({"th": "X"})  # キーが2文字なのでNG
except Exception as e:
    print(type(e).__name__, ":", e)
実行結果
ValueError : dictionary keys must be strings of length 1 or integers

部分文字列の置換をしたい場合はstr.replacere.subを使います。

Python初心者向けの使いどころ

正規化やサニタイズに強い

全角記号を半角へ揃える、スマートクォートを通常の引用符へ統一、複数種類のダッシュをハイフンへ統一など、文字ごとの正規化に向いています。

また削除文字を一括指定できるため、入力から不要文字をまとめて除去する用途にも適しています。

maketransの作り方と置換マップ

文字列2本(from,to)でマッピングを作成

等長の2本の文字列で1対1マッピング

str.maketrans(from_str, to_str)は、同じ長さの2つの文字列を受け取り、対応する位置の文字どうしで置換します。

Python
# "abc" を "ABC" へ対応させる
table = str.maketrans("abc", "ABC")
print("abracadabra".translate(table))
実行結果
ABrACAdABrA

長さが一致しない場合はValueErrorになります。

dictでUnicodeコードポイントを指定

ordで細かく制御

辞書でord(文字)をキーにすると、Unicodeコードポイント単位で指定できます。

これにより、特殊文字(丸数字など)の正規化がしやすくなります。

Python
# 丸数字や記号を通常の数字・記号へ
table = str.maketrans({
    ord("①"): "1",
    ord("②"): "2",
    ord("③"): "3",
    ord("—"): "-",   # エムダッシュをハイフンへ
})
print("得点①—③を選択".translate(table))
実行結果
得点1-3を選択

第3引数で削除文字を指定(delete)

まとめて消すなら第3引数

str.maketrans(from_str, to_str, delete_str)の第3引数delete_strに含む文字は削除されます。

置換と削除を同時に仕込めます。

Python
# 数字を全角→半角に、かつカンマと空白は削除
table = str.maketrans("0123456789", "0123456789", ", ")
print("1,2 3".translate(table))
実行結果
123

同じ「削除」は辞書で文字: Noneと書いてもOKです。

1文字を複数文字に展開する

1→Nの展開が可能

1文字を複数文字へ置換できます。

例えばドイツ語のßssに展開します。

Python
table = str.maketrans({"ß": "ss", "æ": "ae"})
print("straße • encyclopædia".translate(table))
実行結果
strasse • encyclopaedia

replaceとの違いと使い分け

順序に依存しない同時置換が可能

置換順序の罠を回避

translateは同時置換なので、入れ替え(スワップ)でも安全です。

replaceの連続適用は順序に依存して壊れることがあります。

Python
s = "ABABA"

# replaceの連鎖(順序依存)
r1 = s.replace("A", "B").replace("B", "A")

# translateは同時置換なので意図通りに入れ替わる
table = str.maketrans({"A": "B", "B": "A"})
r2 = s.translate(table)

print("replace:", r1)
print("translate:", r2)
実行結果
replace: AAAAA
translate: BABAB

回数指定(count)はreplaceのみ

一部だけ置換したいならreplace

replaceにはcount引数があり、最初のn回だけ置換といった制御が可能です。

translateには回数指定がありません。

Python
s = "spam spam spam"
print(s.replace("spam", "eggs", 1))  # 最初の1回だけ置換
実行結果
eggs spam spam

大量置換でのパフォーマンスはtranslateが有利

1パスで高速

多種類の文字を一括で処理するならtranslateが有利です。

以下は簡易ベンチマーク例です(結果は環境により変化します)。

Python
import timeit

text = "A-B_C:D;E " * 10000
table = str.maketrans("", "", "-_:; ")

def via_translate():
    return text.translate(table)

def via_replace_chain():
    return text.replace("-", "").replace("_", "").replace(":", "").replace(";", "").replace(" ", "")

# ベンチマーク
t1 = timeit.timeit(via_translate, number=50)
t2 = timeit.timeit(via_replace_chain, number=50)
print("translate    :", t1)
print("replace chain:", t2)
実行結果
translate    : 0.0015
replace chain: 0.016
ポイント

str.maketrans("", "", "-_:; ") のようにすると、一気に複数文字を削除できる。

一般にtranslateは1回の走査で完結するのに対し、置換を何度も繰り返すと文字列の再生成コストが嵩みます。

正規表現が必要ならre.subとの使い分け

パターン一致はre.sub

translate部分文字列やパターンを扱えません。

繰り返し空白を1つに縮約するような場合はre.subが適します。

Python
import re
s = "a   b\t\tc\n  d"
print(re.sub(r"\s+", " ", s).strip())
実行結果
a b c d

まとめると、単純な文字ごとの正規化や大量削除→translate、部分文字列や回数制御→replace、パターン→re.subという住み分けになります。

以下に要点の比較表を示します。

特徴translatereplacere.sub
同時置換(順序非依存)強い弱い(順序依存)可(工夫次第)
回数指定なしありあり(パターンに依存)
大量の文字種に対する性能有利連鎖で不利パターンによりけり
パターン表現不可不可可能

例で学ぶstr.translate

記号を一括置換して正規化する例

スマートクォートや長音・ダッシュ類の統一

テキスト収集時に混ざりがちな記号をASCIIへ統一します。

Python
text = '“Python”—それは「汎用」言語。価格は1,234円。メールはfoo—bar@example.com'
# 代表的なUnicode記号をASCIIへ正規化
table = str.maketrans({
    "“": '"', "”": '"',
    "‘": "'", "’": "'",
    "—": "-", "–": "-", "−": "-",  # ダッシュ/マイナスもハイフンへ
    "〜": "~", "~": "~",
    ":": ":", ";": ";",
    "(": "(", ")": ")",
    "[": "[", "]": "]",
    "{": "{", "}": "}",
    ",": ",", "。": ".",
    "1": "1", "2": "2", "3": "3", "4": "4",
})
normalized = text.translate(table)
print(normalized)
実行結果
"Python"-それは「汎用」言語.価格は1,234円.メールはfoo-bar@example.com

多様な記号を一度に正規化できるのが大きな利点です。

必要に応じてマップを足していけます。

数字以外を削除する例

入力に含まれる非数字だけを狙って消す

全Unicodeから非数字を列挙するのは現実的ではないため、対象文字列に現れた非数字のみを削除指定する方法が簡便です。

Python
s = "注文番号: No.AB-123 456-xyz"
# 文字列中に現れる、数字以外の文字を集めて削除指定
delete_chars = "".join({ch for ch in s if not ch.isdigit()})
table = str.maketrans("", "", delete_chars)
digits_only = s.translate(table)
print(digits_only)
実行結果
123456

入力ごとに削除集合を作るため、過剰削除を避けやすいのが利点です。

固定の入力規格がある場合は、あらかじめ許容文字以外を列挙して削除するマップを作るのも有効です。

複数の空白や記号をまとめて削除する例

ホワイトスペースと句読点を一括除去

stringモジュールの定義済み集合を活用すると便利です。

Python
import string

s = " \tHello,-_ World!! \nNext\tLine... "
# 空白類(string.whitespace)と句読点(string.punctuation)を削除
delete = string.whitespace + string.punctuation
table = str.maketrans("", "", delete)
cleaned = s.translate(table)
print(cleaned)
実行結果
HelloWorldNextLine

translateなら「削りたい文字の種類」を並べるだけで、1回の処理で一気にきれいにできます。

まとめ

str.translateは「文字ごと」の同時置換・削除を高速に行える標準機能です。

str.maketransで置換マップを作り、記号・全角半角・特殊文字の正規化や不要文字の除去を1パスで実現できます。

部分文字列の置換は不可という制約はありますが、そこはreplacere.subと適材適所で使い分ければ問題ありません。

実運用では、頻出の正規化ルールをマップとして蓄積し、順序に依存しない同時置換高速性を活かして、堅牢な前処理パイプラインを構築していきましょう。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!