2018年03月11日

言語処理100本ノックでPython入門 #23 - タプル

  

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

■ 問題


問題20で作成したファイルを入力として、以下の問題を解きます。
23. セクション構造
記事中に含まれるセクション名とそのレベル(例えば"== セクション名 =="なら1)を表示せよ.

■ Pythonのコード
import re

def readArticle(filename): with open(filename, 'r', encoding='utf8') as fin: return fin.read()
def getSections(article): for s in article.split('\n'): m = re.match(r'(=+)\s*([^=\s]+)\s*=+', s) if m: yield m.group(2), len(m.group(1)) - 1
def main(): article = readArticle('england-article.txt') for name, level in getSections(article): print(name, level)
if __name__ == '__main__': main()

■ どう解くか

'england-article.txt'は問題20で作成したファイルです。これを入力ファイルとしています。
No22 とほぼ同じような構造で書けますね。

変更したのは、getCategoriesメソッドの名前をgetSectionsに変え、中身と戻り値を若干変更しただけです。

def getSections(article):
    for s in article.split('\n'):
        m = re.match(r'(=+)\s*([^=\s]+)\s*=+', s)
        if m:
            yield m.group(2), len(m.group(1)) - 1

このメソッドで、レベルをどう取り出そうか少し悩みましたが、`=` 連続もグループ化して、その長さを求めればOKですね。 それと、= と セクション名の間に空白がある場合もあるので、`\s*`で空白有りにも対応しています。


■ タプル


Pythonで初めてタプル使いました。yieldで列挙するときに、タプルを使っています。

yield m.group(2), len(m.group(1)) - 1

呼び出し元での参照も簡単です。
for name, level in getSections(article):
        print(name, level)

やはり、言語そのものでタプルをサポートしているのでとても便利です。


■ 結果

国名 1
歴史 1
地理 1
気候 2
政治 1
外交と軍事 1
地方行政区分 1
主要都市 2
科学技術 1
経済 1
鉱業 2
農業 2
貿易 2
通貨 2
企業 2
交通 1
道路 2
鉄道 2
海運 2
航空 2
通信 1
国民 1
言語 2
宗教 2
婚姻 2
教育 2
文化 1
食文化 2
文学 2
哲学 2
音楽 2
イギリスのポピュラー音楽 3
映画 2