テキストファイルを逆順でナンバリング
弊社内のHaskell勉強会に参加したので、その時のお題をPythonでも書いてみます。
(元のお題は複数のファイル名を受け付けていますが、ここでは1つだけに変えています)
ちなみにitertools.countの増分はPython 2.7からなので、それ以降じゃないと動きません。
from itertools import count, izip def numbering(filename, counter, output): f = open(filename) nlines = sum(1 for line in f) f.seek(0) for i,line in izip(counter(nlines), f): output(i, line) def revcounter(n): return count(n - 1, -1) def numboutput(i, line): print '%6d' % i, line, numbering('readme.txt', revcounter, numboutput)
13 関数プログラミング入門 Haskellで学ぶ原理と技法 12 Richard Bird 著 11 山下伸夫 訳 10 定価:3990円 9 A5 448頁 8 ISBN 978-4-274-06896-6 7 Haskellで学ぶ関数プログラミングの入門書 6 本書はHaskell、OCaml、F#、Scalaといった言語の普及により 5 改めて注目される「関数プログラミング」の理論を体系的に学ぶ教科書 4 "Introduction to Functional Programming using Haskell" 3(Prentice Hall, 1998)の翻訳です。 2 関数プログラミングにおける評価戦略、データ構造、計算量、型、 1 モナドの仕組みなどについて、Haskellによるシンプルなコードを 0 例に解説しています。
Haskellなどの関数型では、やりたいことに名前だけ決めておき、型に気をつけながら処理を書き進めていくトップダウンが基本みたいです。ただそれを手続き型言語であるPythonで単にまねたところで意味はないような気もしたので、あくまで「変えたい機能は引数で渡す」というところだけ意識した書き方をしました。
このお題では「ファイルを読み込んで1行に数を振る部分」「振るための数を作る部分」「最終的に出力する部分」と分解しました。ファイルの全行を読み込んでリストを作ることはしたくなかったので、メインの部分でファイルを1度読んで行数を取得しています。
でもこれパフォーマンス的にはどうなんでしょう? ファイルキャッシュがあれば意外と2度読みしても速かったりするかも。でもキャッシュが利かないと基本的にディスクは物理装置なんだし、やはり1回読みでリスト作ってという方が速いんでしょうね。