Sunday 16 March 2014

Python の文字列置換で便利な str.translate

Python で文字列中の文字置換,というと簡単なのだと str.replace, 複雑化すると import re あたりを思いつくが,
'l' を '1' に, 'k' を 'z' に,'y' を ';' に置換したい
みたいな微妙な場合には str.translate が便利よ,という話.


上のはもちろんずらずらつなげて
mystring.replace('l','1').replace('k','z').replace('y',';')
でもいけるが,これはさすがにやりたくない.
実は atcoder でのこの回答 (@regular contest #019-A) で知ったのだが,translate というメソッドがある.

python 2.x と 3.x で扱いが若干違うようで,python3.x なら
x = str.maketrans("lky", "1z;")
print(x, type(x))
# {121: 59, 107: 122, 108: 49} <class 'dict'>
mystring.translate(x)
という感じで使用できる.ここで str.maketransdict を返す static method で,引数は 1-3 個.引数は i) 本人が返してるような,Unicode ordinal/char => Unicode ordinal/string of arbitrary length/None な dict (str.maketrans({'l':"there"}) とかもできる), ii) 引数2つ(同じ長さの string)で 「こっちの文字列中の文字を」「対応するこっちの文字で置換」 iii)3つ目の引数を与えるとそれは None に map される文字群,ということになっている.
そしてそれを str.translate が受け取る,という形で置換ができるわけだ.


一方 python 2 系で使うときはこんな感じ.
import string
x = string.maketrans("lky", "1z;")
print x, type(x) 
# '\x00\x01\x02\x03\x04\x05\x06......ghijz1mn...\xff' <type 'str'>
mystring.translate(a)

ご覧の通り string.maketransstr の static method というわけではないようで,またここでは 256 文字の羅列で変換テーブルが作られている. str.translate が使えるのは同様だが,3.x ではこれは map だけを受け取るのに対して str.translate(table,[deletechars]) としてここで第二引数を受け取って文字列消去を行えるようだ(消去は置換より前に行われる). string.translate(s,table,[deletechars]) という書き方もできるみたい.


というわけで案外便利そうな(そして 2.x と 3.x で扱いの違う) translate method のお話でした. Atcoder みたいに他の人の回答も見られるやつは,簡単な問題でも案外たまにみるといいことがあったりする.

No comments:

Post a Comment