2018年04月04日

言語処理100本ノックでPython入門 #32 - タプルをリスト内包表記で利用する

  
言語処理100本ノック 2015の問題32に挑戦です。

このあたりまで来ると、Pythonの言語機能を習得するという問題から、やりたいことをどうコードに落とし込むかという問題に焦点が移ってきていますね。

■ 問題


夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存せよ.このファイルを用いて,以下の問に対応するプログラムを実装せよ. なお,問題37, 38, 39はmatplotlibもしくはGnuplotを用いるとよい.

32. 動詞の原形
動詞の原形をすべて抽出せよ.

■ Pythonのコード
import re

def analyze():
    lines = []
    sentence = []
    with open('neko.txt.mecab', 'r', encoding='utf8') as fin:
        for line in fin:
            words = re.split(r'\t|,|\n', line)
            if words[0] == 'EOS':
                if sentence:
                    lines.append(sentence)
                    sentence = []
                continue
            sentence.append({
                "surface": words[0],
                "base": words[7],
                "pos": words[1],
                "pos1": words[2],
            })
    return lines

def extractVerbs(lines):
    for sentense in lines:
        seq = filter(lambda w: w['pos'] == '動詞', sentense)
        yield from map(lambda w: (w['surface'], w['base']), seq)

def main():
    article = analyze()
    verbs = [(surface, base) for surface, base in extractVerbs(article)]
    print(verbs[:50])

if __name__ == '__main__':
    main()

■ ちょっとコードの解説


analyze関数は、問題30で作成したものと同じです。 せっかっくなので、動詞と原型を対で取得してみました。タプルを使っています。
(w['surface'], w['base'])
というコードを map関数の中で使って、yield fromで列挙しています。

main関数では、これを受け取り、リスト内包表記使ってリストに格納しています。
verbs = [(surface, base) for surface, base in extractVerbs(article)]
一つ目を取り出すならば、
print(verbs[0][0], verbs[0][1])
これで、
生れ 生れる
が表示されます。

ファイルに出力せよとか、表示せよとかの指定がないので、抽出したタプルのリストの先頭50個をprintに渡しています。

■ 結果

先頭50個を出力しています。
[('生れ', '生れる'), ('つか', 'つく'), ('し', 'する'), ('泣い', '泣く'), ('し', 'する'), ('いる', 'いる'), ('始め', '始める'), ('見', '見る'), ('聞く', '聞く'), ('捕え', '捕える'), ('煮', '煮る'), ('食う', '食う'), ('思わ', '思う'), ('載せ', '載せる'), ('られ', 'られる'), ('持ち上げ', '持ち上げる'), ('られ', 'られる'), ('し', 'する'), ('あっ', 'ある'), ('落ちつい', '落ちつく'), ('見', '見る'), ('見', '見る'), ('思っ', '思う'), ('残っ', '残る'), ('いる', 'いる'), ('さ', 'する'), ('れ', 'れる'), ('し', 'する'), ('逢っ', '逢う'), ('出会わ', '出会う'), ('し', 'する'), ('のみ', 'のむ'), ('なら', 'なる'), ('し', 'する'), ('いる', 'いる'), ('吹く', '吹く'), ('せ', 'する'), ('弱っ', '弱る'), ('飲む', '飲む'), ('知っ', '知る'), ('坐っ', '坐る'), ('おっ', 'おる'), ('する', 'する'), ('し', 'する'), ('始め', '始める'), ('動く', '動く'), ('動く', '動く'), ('分ら', '分る'), ('廻る', '廻る'), ('なる', 'なる')]