素人の言語処理100本ノック:18


言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。

第2章: UNIXコマンドの基礎

hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.

18.各行を3コラム目の数値の降順にソート

各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).

出来上がったコード:

main.py
# coding: utf-8

fname = 'hightemp.txt'
lines = open(fname).readlines()
lines.sort(key=lambda line: float(line.split('\t')[2]), reverse=True)

for line in lines:
    print(line, end='')

実行結果:

端末
高知県   江川崎   41  2013-08-12
埼玉県   熊谷  40.9    2007-08-16
岐阜県   多治見   40.9    2007-08-16
山形県   山形  40.8    1933-07-25
山梨県   甲府  40.7    2013-08-10
和歌山県    かつらぎ    40.6    1994-08-08
静岡県   天竜  40.6    1994-08-04
山梨県   勝沼  40.5    2013-08-10
埼玉県   越谷  40.4    2007-08-16
群馬県   館林  40.3    2007-08-16
群馬県   上里見   40.3    1998-07-04
愛知県   愛西  40.3    1994-08-05
千葉県   牛久  40.2    2004-07-20
静岡県   佐久間   40.2    2001-07-24
愛媛県   宇和島   40.2    1927-07-22
山形県   酒田  40.1    1978-08-03
岐阜県   美濃  40  2007-08-16
群馬県   前橋  40  2001-07-24
千葉県   茂原  39.9    2013-08-11
埼玉県   鳩山  39.9    1997-07-05
大阪府   豊中  39.9    1994-08-08
山梨県   大月  39.9    1990-07-19
山形県   鶴岡  39.9    1978-08-03
愛知県   名古屋   39.9    1942-08-02

UNIXコマンド確認用のシェルスクリプト:

test.sh
#!/bin/sh

# 3カラム目を数値として逆順ソート
sort hightemp.txt --key=3,3 --numeric-sort --reverse > result_test.txt

# Pythonのプログラムで実行
python main.py > result.txt

# 結果の確認
diff --report-identical-files result.txt result_test.txt

結果の確認:

端末
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/18$ ./test.sh
10d9
< 群馬県 館林  40.3    2007-08-16
11a11
> 群馬県 館林  40.3    2007-08-16
17d16
< 岐阜県 美濃  40  2007-08-16
19,20c18
< 千葉県 茂原  39.9    2013-08-11
< 埼玉県 鳩山  39.9    1997-07-05
---
> 岐阜県 美濃  40  2007-08-16
21a20
> 千葉県 茂原  39.9    2013-08-11
23a23
> 埼玉県 鳩山  39.9    1997-07-05

diffで違いが検出されてしまいましたが、3カラム目の気温は同値があるので、その部分で違うのは仕方がないでしょう。

ラムダ式

今回初めてラムダ式を使ってみました。lambda line: float(line.split('\t')[2])の部分です。与えられた文字列lineに対して、¥t区切りで分割した3カラム目をfloatとして返す、という関数の代わりに使っています。ただ、少し分かりにくくなりますね。内包表記もそうですが、この辺は慣れもあるかとは思います。

ちなみにPythonのドキュメントの小さな関数とラムダ式の解説では、著者の方はラムダなしのスタイルが好みとのことでした。

ソートの型

ソートの時は対象データの型に注意が必要です。
今回の対象データでは、ラムダ式でfloatに変換し忘れたり、UNIXコマンドのsort--numeric-sortをつけ忘れても正しい結果になりますが、もし気温が5度の場所が混ざっていたりすると、気温が一番低いにも関わらず先頭に来てしまいます。
 
19本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。