Pythonでeach_slice

http://blog.livedoor.jp/dankogai/archives/51838970.html

このエントリを見て、PythonRubyのeach_sliceを書くとしたらどうなるだろうと思ってやってみた。

これだと、要素数がnで割り切れない場合は余りの分は返されない。

def each_slice(n, seq):
    next = iter(seq).next
    r = range(n)
    while True:
        yield [next() for i in r]

>>> for x in each_slice(5, range(21)):
>>> print x
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19]

これなら余りも返ってくるけど、StopIterationが伝播されないからシーケンスの終了を自分でチェックする必要がある。

def each_slice(n, seq):
    next = iter(seq).next
    r = range(n)
    item = list(next() for i in r)
    while item:
        yield item
        item = list(next() for i in r)

>>> for x in each_slice(5, range(21)):
>>> print x
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19]
[20]

groupbyを使ったパターン。無駄な計算が入るし効率はよくないよね。

from itertools import groupby
def each_slice(n, seq):
    for k, group in groupby(enumerate(seq), lambda x:x[0]//n):
        yield [x[0] for x in group]

>>> for x in each_slice(5, range(21)):
>>> print x
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19]
[20]

全要素数がnで割り切れない場合もちゃんと最後まで要素nのリストを返す方が使いやすいから、そうなるとこうかな。

from itertools import chain
def each_slice(n, seq):
    next = iter(chain(seq, [None]*(n-1))).next
    r = range(n)
    while True:
        yield [next() for i in r]

>>> for x in each_slice(5, range(21)):
>>> print x
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19]
[20, None, None, None, None]

結局、itertoolsのドキュメントに載ってるgrouperが一番すっきりしてますね。

from itertools import izip_longest
def each_slice(n, seq):
    args = [iter(seq)] * n
    return izip_longest(fillvalue=None, *args)

(参考) http://stackoverflow.com/questions/3833589/python-equivalent-of-rubys-each-slicecount

TortoiseBzr 0.7.0 Comming soon

もうすぐTortoiseBzr 0.7.0をリリースしようと思うので、あたらしい機能を簡単に紹介します。
#ちゃんとマニュアル書けよ。

ちなみに、今回からコードネームを付けることにしました。
0.7.0のコードネームはCassiopeia、元ネタはミヒャエル・エンデ「モモ」から。

続きを読む

unittestモジュールでparameterized test

最近は、Pythonのテストフレームワークっていうとnoseがいいとか、py.testがいいとか色々聞きますが、Bazaarのテストライブラリはunittest + testtoolsベースなので、プラグインとかを作ろうと思うとその辺を使うことになります。

続きを読む

TokyoMercurial #3 行ってきた / WinMergeのインスタンスマネジメント

TokyoMercurial#3 - Togetter

Mercurial派にすり寄るべく、4/14に開催されたTokyoMercurial #3に参加してきました。
もくもく会と言いつつちっとももくもくにならないのはもはや定番って感じ。

続きを読む

TortoiseBzr高速化のためのメモ

ほぼ自分用メモ

TortoiseBzrのアイコンオーバーレイは、内部でbzr statusと同じ処理が実行されているわけだけれども、これがあまり速くない。

この処理でやってることは主に2つで、

  1. .bzr/checkout配下のdirstateやconflictsファイルを読み込んで、各ファイルのバージョン管理状態を確認する。
  2. 作業コピー内の各ファイルの更新時刻を取得して、dirstate内に記録された更新時刻と比較することによって変更されているかどうかをチェックする。必要に応じてファイルのsha1も取得する。

dirstateなんかは、数万ファイルの作業コピーであってもたかだか数MBのファイルなので読み込みは一瞬で終わる。かかっている時間の99%は2の方の処理。

でも、TortoiseBzrは作業コピー内のファイルの更新を監視してるので、本当は2の処理なんて起動後1回だけ実行すればあとはもう必要ない。その辺を踏まえて再実装すればアイコンオーバーレイが劇的に高速化するはず。

なんだけど、誰かやってくんないかなー。

TokyoMercurial #1 行ってきた

いいかげんMercurialもちゃんと使えるようにならんとなあということで、 id:troter さん主催のTokyoMercurial行ってきました。
partake.in

やったこと

TortoiseHgのコードリーディング

Shellエクステンション周りを中心に、ちょっとだけコードを読みました。

TracBlockdiagPluginをBitbucketに引越し

DVCSに慣れると、SVNにコミットするのに抵抗を感じるようになりますし、パッチをもらったりとかもDVCSの方が楽になるので、TracBlockdiagPluginのコードをTracHacksからBitbucketに移しました。(まだTracHacksの方のWikiは修正してませんが)
Launchpadでもよかったんですが、Blockdiag本体もBitbucketですし。

といいつつ、ほとんどの時間は藤原さん(id:flying-foozy)やtroterさんと他の参加者の方とのやりとり(主に歴史改変ネタなど)に耳を傾けてました。Mercurial的にはちょっと無い贅沢な環境ですね。

以下とりとめのない感想など。

  • TortoiseHgのGUIがすごく進化してて、ねたましい。
  • ついでに言うとアイコンオーバーレイはものすごく割り切った作り。ファイルの更新には一切反応せず、dirstateファイルとExplorerで開いてるフォルダ直下のファイルのタイムスタンプ見てるだけ。
    変更監視はそれなりの負荷になるし、アイコンオーバーレイなんてそれで十分なのかもな。
  • やっぱりMQがちゃんと使えないと話にならないので次回までに身につけておきたい。
  • みんな若いよねー。

あ、あと、以前からTwitterで色々とお世話になっていた世界の小宮さんにようやく挨拶することができました。
Mercurial関係ないけどこれも大きな収穫です。