schedule2018-07-21

16. ファイルをN分割する

はじめに

言語処理100本ノック 2015

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

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

環境

Python3.6

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

問題

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

16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.

解答:Python

points

  • コマンドラインで分割数とファイル名を受け取る
  • 行を分割数で等分する
  • 出力ファイル名が被らないように、接尾語をつける

program

import sys


def readlines_file(file_name):
    with open(file_name, 'r') as file:
        return file.readlines()


def save_file(file_name, text):
    with open(file_name, 'w') as file:
        file.write(text)


def suffix(i):
    # 3桁の0埋め
    return "{:03d}".format(i)


N, file_name, prefix = sys.argv[1:4]


lines = readlines_file(file_name)

# 切り分ける行数
limit = len(lines) // int(N)

for i in range(int(N)):
    offset = i * limit
    # 分割
    text = lines[offset: offset + limit]
    save_file(prefix + suffix(i), "".join(text))

コマンド

$ python ファイルをN分割する.py 3 hightemp.txt out_

出力

out_000

高知県\t江川崎\t41\t2013-08-12
埼玉県\t熊谷\t40.9\t2007-08-16
岐阜県\t多治見\t40.9\t2007-08-16
山形県\t山形\t40.8\t1933-07-25
山梨県\t甲府\t40.7\t2013-08-10
和歌山県\tかつらぎ\t40.6\t1994-08-08
静岡県\t天竜\t40.6\t1994-08-04
山梨県\t勝沼\t40.5\t2013-08-10

out_001

埼玉県\t越谷\t40.4\t2007-08-16
群馬県\t館林\t40.3\t2007-08-16
群馬県\t上里見\t40.3\t1998-07-04
愛知県\t愛西\t40.3\t1994-08-05
千葉県\t牛久\t40.2\t2004-07-20
静岡県\t佐久間\t40.2\t2001-07-24
愛媛県\t宇和島\t40.2\t1927-07-22
山形県\t酒田\t40.1\t1978-08-03

out_002

岐阜県\t美濃\t40\t2007-08-16
群馬県\t前橋\t40\t2001-07-24
千葉県\t茂原\t39.9\t2013-08-11
埼玉県\t鳩山\t39.9\t1997-07-05
大阪府\t豊中\t39.9\t1994-08-08
山梨県\t大月\t39.9\t1990-07-19
山形県\t鶴岡\t39.9\t1978-08-03
愛知県\t名古屋\t39.9\t1942-08-02

解説

コマンドライン引数は分割数N、 分割するファイル名file_name、出力するファイル名の文字prefixを受け取ります。

N, file_name, prefix = sys.argv[1:4]

分割数から、1つあたりの行数を求めます。

# 切り分ける行数
limit = len(lines) // int(N)

//は切り捨て除算です。割り切れない場合も整数になるようにしました。

for i in range(int(N)):
    offset = i * limit
    # 分割
    text = lines[offset: offset + limit]
    save_file(prefix + suffix(i), "".join(text))

ここで、分割数の分だけ行を取り出し、ファイルに書き込んでいます。

ファイル名が被らないように接尾語をつけます。

def suffix(i):
    # 3桁の0埋め
    return "{:03d}".format(i)

suffix(i)は数値をゼロ埋めした文字列を返すようにしています。

解答:UNIXコマンド

考え中。。。

続いての記事

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

前の問題 : 15. 末尾のN行を出力

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