schedule2018-07-21

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

はじめに

言語処理100本ノック 2015

Pythonを勉強するため、東京工業大学の岡崎教授が出題されている言語処理100本ノック 2015を解いていきます。

より深く理解するため、別解や利用したライブラリの解説もまとめていきます。

環境

Python3.6

OS : mac
2章からUNIXコマンドの問題ですが、macもターミナルから利用できるようです。

問題

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

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

解答:Python

points

  • ファイルの内容を2次元配列にする
  • 行の特定の列でソートする
  • 2次元配列から元の形式に復元する

program

def read_file(file_name):
    with open(file_name, 'r') as file:
        return file.read()

lines = read_file('hightemp.txt').split('')

# 空行の削除
lines = list(filter(lambda line: line != '', lines))

# 行をタブで分割
lines = list(map(lambda line: line.split('\t'), lines))

# 指定列で逆順ソート
lines = sorted(lines, key=lambda x: x[2], reverse=True)

# タブ区切りで行を結合
lines = list(map(lambda x: "\t".join(x), lines))

print("".join(lines))

出力

高知県  江川崎  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

解説

lines = read_file('hightemp.txt').split('')

ここと、

# 行をタブで分割
lines = list(map(lambda line: line.split('\t'), lines))

この二つの行で、改行とタブで区切られた文字列から、2次元配列に置き換えます。

# 指定列で逆順ソート
lines = sorted(lines, key=lambda x: x[2], reverse=True)

sorted()は2次元配列もソートすることができます。
デフォルトだと1列目を基準にソートするため、keyにlambdaを使って3列目を使ってソートするよう指定してあげます。 また、逆順にするため、reverse=Trueとします。デフォルトはreverse=Falseとしてあり昇順です。

これで、行を崩さずに並び替えることができます。

# タブ区切りで行を結合
lines = list(map(lambda x: "\t".join(x), lines))

print("".join(lines))

最後に、並び替えた2次元配列から元の書式に戻してあげます。

解答:UNIXコマンド

考え中。。。

続いての記事

Python3で言語処理100本ノックまとめ

前の問題:17. 1列目の文字列の異なり

次の問題:19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる