はじめに
Pythonを行き当たりばったりで触ってきたので
何処までPythonできているのかを見つめ直すために、自然言語処理100本ノックしていきます。
python2ばっかり使っていましたので、慣れるためにpython3でやっていきます。
Python100本ノック(15/100)の続きをやっていきます。
15. 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.
n = input('n line?')
if n.isdigit():
n = int(n)
print(''.join(open('hightemp.txt').readlines()[-n:]))
# tail -n 3 hightemp.txt
# tail -3 hightemp.txt
n line?3
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
readlines
で、配列を取得し[-n:]で後ろの指定行数を取得しました。
16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.
import math
n = input('n line?')
if n.isdigit():
n = int(n)
lines = open('hightemp.txt').readlines()
# lines = list(range(12))
# print(len(lines) / n)
# print(math.ceil(len(lines) / n))
# split -l 6 -d hightemp.txt hoge
print('------\n'.join([''.join(lines[i * n:(i + 1) * n]) for i in range(0, math.ceil(len(lines) / n))]))
n line?6
高知県 江川崎 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
readlines
で配列を取得し、指定行数で割り切れた数ループさせ分割しました。
割り切れない場合は、math.ceil
で切り上げで対応しました。
15と同じく配列に引数を指定する形で、配列の分割を行いました。
UNIXコマントでは、split
に-l 6
というオプションを付け行数分割を行いました。
17. 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.
kens = [line.split()[0] for line in open('hightemp.txt').readlines()]
# sorted(kens, key=lambda x: kens.count(x))
print(set(kens))
# print({k: kens.count(k) for k in set(kens)})
# ひどいコマンドな気がするけど、どうなんだ
# cut -f 1 hightemp.txt | sort | uniq -c
# cut -f 1 hightemp.txt | sort -t \t \u
{'静岡県', '山梨県', '大阪府', '千葉県', '山形県', '埼玉県', '愛知県', '愛媛県', '和歌山県', '高知県', '群馬県', '岐阜県'}
2章の前半と同じく、readlines
で取得し、split
で分解しました。
その後, set
を使い重複の削除を行いました。
UNIXコマンドでは、cutで指定行のみを抽出した後、uniqかsortで重複をなくしました。
18. 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
print(''.join(sorted(open('hightemp.txt').readlines(), key=lambda x: x.split()[2], reverse=True)))
# sort -k3 -r hightemp.txt
高知県 江川崎 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
readlines
で取得後、sorted
でソートしました。
ソートのキーには、lambda式を使い、'split'した後の3カラム目を指定しました。
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.
kens = [line.split()[0] for line in open('hightemp.txt').readlines()]
print('\n'.join(sorted(set(kens), key=lambda x: kens.count(x), reverse=True)))
# cut -f 1 hightemp.txt | sort | uniq -c | sort -r
山梨県
山形県
埼玉県
群馬県
静岡県
千葉県
愛知県
岐阜県
大阪府
愛媛県
和歌山県
高知県
他の問題の応用で、sorted
, set
, lambda
を使ってソートを行いました。
ソートキーは、kens
に何個あるかです。
from collections import Counter
kens = [line.split()[0] for line in open('hightemp.txt').readlines()]
ckens = Counter(kens)
print(ckens)
print(sorted(ckens, key=lambda x: ckens[x], revcerse=True))
Counter
が単語と数の辞書形にしてくれるので、あとは順番変更するだけという形にもできました。
Counter
は使ったことがなかったので、勉強になりました。
collections
には便利な物が多い。
追い焚きグッズがあったけど、少し高めなのでアルミシート湯の上に引いたらどうなるか試してみます。