内包表記

INPUT · スライド

入れ子をほどく

01 / 07

リストの中のリスト

表のようなデータは、リストの中にリストを入れて持つことがある。行ごとにリストを1本、という形だね。

これを「1本の平らなリストにしたい」ことがよくある。for で書くなら、2重に回して append することになるよ。

hyou = [[1, 2], [3, 4]]hira = []for gyou in hyou:    for x in gyou:        hira.append(x)print(hira)

実行結果

[1, 2, 3, 4]

02 / 07

for を2つ並べる

内包表記では、for を2つ続けて書くだけでいい。

[x for gyou in hyou for x in gyou] と書けば、それでもう平らなリストになるよ。

hyou = [[1, 2], [3, 4]]print([x for gyou in hyou for x in gyou])

実行結果

[1, 2, 3, 4]

03 / 07

書く順は外側から

ここがいちばん間違えやすいところ。for は外側から順に並べるんだ。

for 文で書いたときの上から下の順が、内包表記ではそのまま左から右になる。

for gyou in hyou:      →  for gyou in hyou    for x in gyou:     →  for x in gyou

先頭の式だけが前に出て、あとはまったく同じ順。順番を逆にすると gyou がまだ無い状態で使うことになって、NameError になるよ。

hyou = [["あか", "あお"], ["きいろ"]]print([t for gyou in hyou for t in gyou])

実行結果

['あか', 'あお', 'きいろ']

04 / 07

if も足せる

前のレッスンでやった if は、いちばんうしろに足すよ。

平らにしながら絞りこむ、ということが1行でできる。ただしここから急に読みにくくなるので、使う前に一度考えよう。

hyou = [[1, 2], [3, 4]]print([x for gyou in hyou for x in gyou if x % 2 == 0])

実行結果

[2, 4]

05 / 07

組み合わせを作る

for を2つ並べるのは、平らにするためだけじゃない。すべての組み合わせを作るのにも使えるよ。

別々のリストを2つ回せば、外側が1つ進むあいだに内側が全部回る。かけ算の答えの数だけ要素ができるんだ。

saizus = ["S", "M"]iros = ["あか", "あお"]print([f"{s}の{i}" for s in saizus for i in iros])

実行結果

['Sのあか', 'Sのあお', 'Mのあか', 'Mのあお']

06 / 07

角かっこで囲むと行が残る

平らにするのではなく、リストのリストのまま作りたいこともある。そのときは内側をもう一度角かっこで囲むよ。

for を2つ並べたものとは結果の形がまったく違う。角かっこがあるかどうかだけの差なので、読むときは気をつけよう。

print([[x * y for y in range(1, 4)] for x in range(1, 4)])

実行結果

[[1, 2, 3], [2, 4, 6], [3, 6, 9]]

07 / 07

詰めこみすぎると読めなくなる

ここまで来たので、大事な注意を書いておくよ。

内包表記は短く書けるけれど、詰めこみすぎると読めなくなる。3段の入れ子に if が2つ、みたいなコードは、素直に for で書いたほうが親切だ。

短さは目的ではない。読みやすさが目的で、内包表記はたいていの場合それに貢献する——という順序で覚えてほしい。迷ったら for に戻す。それは負けではないよ。

次のレッスンからは、角かっこを別の記号に変えてみよう。