結論: ネストした内包表記のどちらが内側か忘れたら、for ループで書き下した時の順序と同じと思い出す。なんども忘れるのでメモしました。
一重の内包表記
まず基本的な例。
>>> [x * 2 for x in [1,2,3,4,5]]
[2, 4, 6, 8, 10]
[変数を使った式 for 変数 in リスト]
のようにすると、リストのそれぞれの要素に式を適用したリストを作る事が出来ます。
>>> {x: x * 2 for x in [1,2,3,4,5]}
{1: 2, 2: 4, 3: 6, 4: 8, 5: 10}
また {変数を使った式: 変数を使った式: for 変数 in リスト}
のようにすると、リストではなく辞書を作る事が出来ます。
二重の内包表記
この順番をいつも忘れる。。。
>>> [(x, y) for x in [1, 2] for y in ['a', 'b', 'c']]
[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c')]
このように .. for .. in ..
は二重に重ねる事が出来ます。この場合、後に書いた物が内側のループになります。この場合、後に書いた y
が内側のループで、これが細かく回っている間外側の x
がゆっくり回ります。覚え方としては
>>> results = []
>>> for x in [1, 2]:
for y in ['a', 'b', 'c']:
results.append((x, y))
>>> results
[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c')]
のように同じ順番で for
ループを書いたのと同じ動きになります。
二重の内包表記を使った二重リストの展開
と、いうことは後ろのループで前の変数を使えるという事です。例えばネストしたリストを展開したい時、
>>> [item for sublist in [[1,2], [3,4], [5,6]] for item in sublist]
[1, 2, 3, 4, 5, 6]
のようにします。一見技巧的ですが、以下と同じです。なんとなく前の for
が内側のような気がしてしまいますが、外側です。
>>> results = []
>>> for sublist in [[1,2], [3,4], [5,6]]:
for item in sublist:
results.append(item)
>>> results
[1, 2, 3, 4, 5, 6]
二重の内包表記を使った二重リストの式の適用
内包表記の for
の前に内包表記を重ねると、リストの構造を変えないで内側の要素に式を適用する事が出来ます。
>>> [[item * 2 for item in sublist] for sublist in [[1,2], [3,4], [5,6]]]
[[2, 4], [6, 8], [10, 12]]
これは単に式が書ける所に内包表記を書くだけなので直感的だと思います。念のため for
ループで書くとこうなります。
>>> results = []
>>> for sublist in [[1,2], [3,4], [5,6]]:
subresults = []
for item in sublist:
subresults.append(item * 2)
results.append(subresults)
>>> results
[[2, 4], [6, 8], [10, 12]]