【Python基礎】リスト内包表記:二次元リスト(ネストされたリスト)の作成

  • URLをコピーしました!
目次

リスト内包表記

前回、Twitterでのツイートの文字数を正確に数えてくれるライブラリtwitter-text-parserを試してみました。

今回は話題がガラッと変わってリスト内包表記に関してです。

前にリスト内包表記に関してこちらの記事で紹介しました。

またfor文との速度比較なんかをしたりもしています。

最初はなかなかハードルが高かったリスト内包表記ですが、最近ではチラホラと使い始め、それほど苦もなく使えるようになってきました。

そんな折、見つけてしまったのが、リスト内包表記を二重で使用する方法です。

なかなか面白い方法であり、さらにはなかなか難しい方法であるので今回紹介してみようと思います。

それでは始めていきましょう。

リスト内包表記の基本型

まずはリスト内包表記の基本のおさらいからです。

リスト内包表記はfor文を1行で書き、リスト化する方法です。

例えばfor文を使ってこんなプログラムがあったとします。

val1 = []
for i in range(10):
    val1.append(i)

print(val1)

実行結果
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

これをリスト内包表記で書くとこうなります。

val2 = [i for i in range(10)]

print(val2)

実行結果
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

また取り出した変数に関しては、さらに処理をすることも可能です。

val3 = [2*i for i in range(10)]

print(val3)

実行結果
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

if文を使った条件分岐もできるのですが、そこらへんはこちらの記事で解説していますので、よかったらご覧ください。

ここら辺がリスト内包表記の基本です。

二重(ネスト)されたリスト内包表記

それではリスト内包表記を二重にしていきましょう。

ただしリスト内包表記の仕方によって、一次元リストと二次元リストが出来ますので注意が必要です。

その点も踏まえて解説していきます。

一次元リストの場合

まずは二重のリスト内包表記を使いつつ、一次元リストを作成する方法です。

言葉にすると分かりにくいですが、for文を2回使ってこのようなリストを作成したいという状況です。

val4 = []
for i in range(10):
    for j in range(i):
        val4.append(j)
        
print(val4)

[0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8]

for文を使ってループさせ、その結果をさらにループさせるというわけです。

これをリスト内包表記で書くとこうなります。

val5 = [j for i in range(10) for j in range(i)]

print(val5)

実行結果
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8]

リスト内包表記は最初に結果の変数がくるものの、その後は左から順に処理されるため、上記のプログラムになるのです。

二次元リストの場合

次に二重のリスト内包表記を使って二次元リストを作成する方法です。

つまりリスト内包表記を使わない場合はこんな感じのプログラムになります。

val6 = []
for i in range(10):
    val_temp = []
    for j in range(i):
        val_temp.append(j)
    
    val6.append(val_temp)
        
print(val6)

実行結果
[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], 
[0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7, 8]]

これをリスト内包表記にするとこうなります。

val7 = [[j for j in range(i)] for i in range(10)]

print(val7)

実行結果
[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], 
[0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7, 8]]

先ほどリスト内包表記は最初の変数以外は左から処理されるとお話ししましたが、二次元リストを作る場合は2回目のループでリストを作成したいため、前に書くことになります。

失敗例としては最初の変数だけをリストに入れて、一次元リストのリスト内包表記のように書いてしまうパターンです。

val8 = [[j] for i in range(10) for j in range(i)]

print(val8)

実行結果
[[0], [0], [1], [0], [1], [2], [0], [1], [2], [3], [0], [1], [2], [3], [4], [0], [1], [2], 
[3], [4], [5], [0], [1], [2], [3], [4], [5], [6], [0], [1], [2], [3], [4], [5], [6], [7], 
[0], [1], [2], [3], [4], [5], [6], [7], [8]]

ちょっとした書き方の違いで出てくる結果が全然変わってくるので、なかなか奥が深いです。

ということで今回は二重のリスト内包表記を紹介しましたが、ここまでできなくても結構シンプルに書くことができる表記ですので、どんどん使っていきたいものです。

次回はリスト内の各要素の個数をカウントする方法を解説していきます。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次