読者です 読者をやめる 読者になる 読者になる

When it’s ready.

出来るまで出来ない

リスト内包表記がかなり楽しくなってきた。with λ

別にビンゴカードを作りたい訳じゃないけど、http://d.hatena.ne.jp/stog/20090128 ココ観てたらリスト内包表記で作りたくなってきた。最近リスト内包表記がとっても気持ちよくてたまらない。

ビンゴカードは、5x5のカードです。縦の列にはそれぞれ、1-15、16-30・・・と言う範囲からランダムに5つだけ入る。

リストのランダムは

import random
arr = range(10)
random.shuffle(arr)

縦一列の範囲を生成するLCは

[range(1,75)[i*15:(i+1)*15] for i in range(5)]

コレで行けそう。
これらを合体してみると完成しそうやってみる。

import random
[random.shuffle(arr) for arr in [range(1,75)[i*15:(i+1)*15] for i in range(5)]]

悲しい結果が返って来た・・・

[None, None, None, None, None]

どうやら、random.shuffle()は返り値がないらしい。にしても、arrに配列入ってるんだからそのまま処理してくれてもいいのに!ということで、よく分からないまま、lambdaを使って見ると良い気がしてきた。適当にやって見るもよくわからんので、緑のブログなid:nishiohirokazuさんに相談してみた。

f = (lambda xs: random.shuffle(xs) or xs)
f(range(10))

と言うのを教えて貰った。コレでいけそう。

import random
[(lambda xs: random.shuffle(xs) or xs)(xs)[0:5] for xs in [range(1,75)[i*15:(i+1)*15] for i in range(5)]]

完成した。

と、ココまで来て緑の人に

NISHIO: [range(1,76)[i:][:15] for i in range(0,75,15)]
んー15が2回出てくるのが気に入らない

と突っ込まれ素敵なスライスを教えて貰った。早速書きなした。

import random
[(lambda xs: random.shuffle(xs) or xs)(xs)[0:5] for xs in [range(1,76)[i:][:15] for i in range(0,75,15)]]

ラムダもリスト内包表記も勉強になった。今回のorの使い方と、xs[:]のlistのコピーを使って非破壊でシャッフルすることも可能。

 lambda xs: (lambda ys: shuffle(ys) or ys)(xs[:])

リスト内包表記は分かり難いというのが一般的な認識というか見解だと思うけど、

arr = []
for i in range(100):
  if i % 3 == 0:
    arr.append(i * 2)
print arr

と書こうが

print [ x * 2 for x in range(100) if x % 3 == 0]

どっちも、分かりやすいし、どっちも分かり難いと思う。慣れの問題だけな気がする。
慣れは重要。