いまさら・・・
すげぇ。この「いまさら感」がすごすぎる。
メタキャラクタとORの扱い
import sys, re, csv path_dict, path_data = sys.argv[1], sys.argv[2] encoding = 'cp932' col_keyword, col_data = 1, 3 reader = csv.reader(file(path_dict, "rb")) keyword = [unicode(row[col_keyword], encoding) for row in reader] pattern = re.compile(u"(" + u"|".join(keyword) + u")") for row in csv.reader(file(path_data, "rb")): print pattern.sub(r"(\1)", unicode(row[col_data], encoding)).encode(encoding)
sys.argv の長さをチェックしていないとか、csv モジュールは ascii の範囲外での動作が保証されていないとか、encoding は locale.getpreferredencoding() でとったほうがいいんじゃないかとか、いろいろ細かいことはあるんだけど、正規表現の生成がまずすぎる。10人以上もブックマークしておいて、だれも気づかんかなぁ。どっちかというと誰もツッコミを入れない点にびっくりだ。
さて、一応問題の解説。
pattern = re.compile(u"(" + u"|".join(keyword) + "u"))
ってやっているけど、これじゃ keyword*1 に "." とか "?" とかのメタキャラクタを含む文字がきたらひどいことになる。単純文字列マッチングなら
pattern = re.compile(u"(" + u"|".join(re.escape(k) for k in keyword) + u")")
とするべき*2。
続きを読むUnicodeオブジェクトへの変換コスト
unicode(s, enc) より s.decode(enc) が早くて decoder(s)[0] は もっと早いという話を聞いたので試してみた。
#!/usr/bin/env python # coding: cp932 from timeit import Timer import codecs decoder = codecs.getdecoder('cp932') setup = 'from __main__ import decoder' print Timer("unicode('日本語', 'cp932')", setup).timeit() print Timer("'日本語'.decode('cp932')", setup).timeit() print Timer("decoder('日本語')[0]", setup).timeit()
結果
2.01834758328 1.65165069862 0.97344774266
おぉ、本当だ。
まぁ、これがプログラム中で支配的な項目になるかといえば多分そんなことはないので、好きなやり方でやるのが吉。