pythonでゴリゴリ処理を書いていると、「とりあえずzipでまとめといて後からほぐす」的な処理をうっかり書いてしまうことがある(本当にそのデータフローが最適なの? という疑問は常にあるのだけど、ループ処理の都合でその方が書きやすかったりすると特にそうなりやすい)。
問題は「どうやって元に戻すか」で、色んなやり方があり、基本的にあまり綺麗なやり方はない。
たとえば、こういう処理を書く人も多いのではないだろうか。
d = list(zip(a, b, c)) ... a2 = [x[0] for x in d] b2 = [x[1] for x in d] c2 = [x[2] for x in d]
もうちょっとエレガントにならないのか? ということを考えてみる。そのためには、そもそもzipは配列でいうところの転置にあたる(ちょっと違うが非常に近い)ということを知っていないといけない。
>>> a = [1,2,3] >>> b = [4,5,6] >>> c = [7,8,9] >>> d = list(zip(a,b,c)) >>> d [(1, 4, 7), #読みやすいように改行してみたよ! (2, 5, 8), (3, 6, 9)]
これが転置だと思えば、もう一回転置すれば元に戻るなと思える。ただし、zipの返り値はジェネレータで、ジェネレータのままだと扱いづらいのでlistに変換したりする人が多いと思うが、そうすると外側に余計なlistが増える。
アスタリスクで外せば良い。
>>> a2, b2, c2 = list(zip(*d)) >>> a2 (1, 2, 3) >>> b2 (4, 5, 6) >>> c2 (9, 8, 7)
タプルになっちゃってるけど、構わないならこれで良い。
ただ、これを積極的に使うべきか? というと非常に微妙なところで、慣れていないと逆に可読性が下がる気がする。相対的にスマートではあるのだけど。