バッチ化とmap(None, *a)とzip(*a)
バッチ化はgroupbyを使う方法とisliceを使う方法は前に紹介しましたが、こちらの方がシンプルでいいかも(イテレータではないのでパフォーマンスの配慮は必要ですが)。
>>> x = xrange(1, 32) >>> map(None, *([iter(x)] * 7)) [(1, 2, 3, 4, 5, 6, 7), (8, 9, 10, 11, 12, 13, 14), (15, 16, 17, 18, 19, 20, 21), (22, 23, 24, 25, 26, 27, 28), (29, 30, 31, None, None, None, None)]
([iter(x)] * 7)てのは同じイテレータの参照を7つ並べたリストです。リストの要素をすべて順番にアクセスするとイテレータから7回取り出すのと同じになります。[mutable_object] * nは実体の同じものが並ぶだけなので普段使いませんが、こういう使い方もあるのかなと。
map(None, *a) はいわば itertools.izip_longest(*a) の非イテレータ版です。zip(*a) だと最短要素で終了してしまうところを最長要素まで取り出して、取れない個所はNoneで埋めてくれます。
>>> x = [(1, 2), (3, 4, 5), (6,)] >>> zip(*x) [(1, 3, 6)] >>> map(None, *x) [(1, 3, 6), (2, 4, None), (None, 5, None)] >>> from itertools import izip, izip_longest >>> list(izip(*x)) [(1, 3, 6)] >>> list(izip_longest(*x)) [(1, 3, 6), (2, 4, None), (None, 5, None)]
おまけ。
最近Rubyのお仕事していて、zipで間違いをやらかして悶絶していたり。
a[0].zip(*a[1..-1])
「うあーRubyはそういうメソッドかー」と理解はするけど、なかなか慣れない。
でもこれって逆にRubyの人からするとPythonの
' '.join(['egg', 'bacon', 'sausage', 'spam'])
とかが慣れないんだろうな...