2018年01月16日

言語処理100本ノックでPython入門 #03 - 正規表現, リスト内包表記

  
今日は、言語処理100本ノックの問題03です。

■ 問題

03. 円周率
"Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."

という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.

■ 初めに書いたコード

import re
text = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics." array = re.split(r'\s|,|\.', text) for s in filter(lambda w: len(w) > 0, array): print(len(s))

■ 次に書いたコード

import re
text = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics." array = re.split(r'\s|,|\.', text) lens = [len(s) for s in filter(lambda w: len(w) > 0, array)] print(lens)

■ 最終版のコード

import re
text = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics." array = re.split(r'\s|,|\.', text) lens = [len(x) for x in array if len(x) > 0] print(lens)

■ 最終版の実行結果

[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

■ 今回学習したこと
 

正規表現の機能を使うには、
import re
と importします。

spliteメソッドで、分割できます。C#にも似たようなメソッドありますし、どの言語にもこういった機能は用意されてるんですね。
text = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
array = re.split(r'\s|,|\.', text)
r'\s|,|\.' が正規表現です。 'r' を前置した文字列リテラルではバックスラッシュを特別扱いしません。
C#の@”..."と同じです。

filter関数は、C#のWhereと同じですね。でもラムダ式書くのが面倒ですね。
for s in filter(lambda w: len(w) > 0, array):
    print(len(s))
これで、空文字を省いてくれます。

リスト内包表現使うと、さらに簡潔に書けます。
lens = [len(s) for s in filter(lambda w: len(w) > 0, array)]
でも、if を使うともっと簡単に書けました。
items = [x for x in array if len(x) > 0]
ちなみに、リスト内包表現のもっとも基本的な書き方は、
lens = [len(x) for x in items]
といった写像処理ですね。

以前、HaskellやF#をすこし勉強したので、リスト内包表現は意外と違和感なく使えました。

でもpythonのラムダ式、これはC#の方が良いですね。アロー式が使えればもっと簡単に書けるのにね。