HOWTO · Python

Python で 2つ以上のリストを連結する方法

このチュートリアルでは、Python で2つ以上のリストを連結する方法を紹介し、新しいリストを作る場合と既存のリストを更新する場合の選び方を説明します。

このページの内容

新しいリストを作る場合は +、既存のリストに要素を追加する場合は extend() または += を使います。複数のリストを扱うなら、アンパック構文は簡潔に書けます。値をイテレーターとして処理したい場合は itertools.chain() が便利です。以下の例では同じリストを使い、それぞれの結果を確認できます。

Python のリスト は順序を保って要素を格納し、いくつかの方法で結合できます。元のリストを変更するか、次の処理でリストとイテレーターのどちらが必要かに応じて方法を選びましょう。

+ 演算子でリストを連結する

+ 演算子は新しいリストを作成し、元の2つのリストは変更しません。2つ以上のリストに使え、+ を追加するたびに別のリストを結合できます。

first = [1, 2, 3]
second = [4, 5]
third = [6, 7]
combined = first + second + third
print(combined)

たとえば first = first + second と代入すると、first は結合後の新しいリストを参照します。元のリストオブジェクトがその場で拡張されるわけではありません。元のリストをそのまま使える状態にしておきたい場合は + を使うとよいでしょう。

extend() でリストを拡張する

extend() は、呼び出したリストの末尾にイテラブルの各要素を追加します。対象のリストを変更し、戻り値は None です。そのため、メソッド呼び出しの結果を代入するのではなく、追加先のリストを変数に保持してください。

first = [1, 2, 3]
second = [4, 5]
first.extend(second)

first.append(second) とは動作が異なります。append() は second を1つの入れ子の要素として追加しますが、extend() はその要素を1つずつ追加します。イテラブルにはリストやタプルのほか、別のイテラブルも指定できます。

+= でリストをその場で拡張する

リストに対する += は、右辺のイテラブルの要素を既存のリストに追加します。動作は extend() とよく似ています。

first = [1, 2, 3]
second = [4, 5]
first += second

左辺のリストを更新したい場合、+= は簡潔な選択肢です。一方、first = first + second は新しいリストを作成し、名前 first をそのリストに結び付けます。

アンパック構文でリストを連結する

イテラブルのアンパックを使うと、各リストの要素を新しいリストリテラルに並べられます。2つ以上のリストに対応し、元のリストは変更しません。

first = [1, 2, 3]
second = [4, 5]
third = [6, 7]
combined = [*first, *second, *third]

角括弧内の * は各イテラブルを展開し、要素が平坦に並んだ1つのリストを作ります。このアンパック構文は Python 3.5 で導入されました(PEP 448 を参照)。

itertools.chain() を使う

itertools.chain() は入力されたイテラブルの要素を順番に返します。戻り値はイテレーターです。具体的なリストが必要な場合は list() で囲みます。

from itertools import chain

first = [1, 2, 3]
second = [4, 5]
third = [6, 7]
combined = list(chain(first, second, third))

値をループで処理するだけなら、イテレーターをそのまま使うことで、あらかじめ結合後のリストを作らずに済みます。itertools.chain() の Python ドキュメントも参照してください。

ループまたはリスト内包表記でリストを連結する

各要素に追加の処理を加える場合は、ループが便利です。append() は一度に1つの要素を追加するため、平坦な結果を作るには各入力リストの要素を順に処理します。

lists = [[1, 2, 3], [4, 5], [6, 7]]
combined = []
for current in lists:
    for item in current:
        combined.append(item)

リスト内包表記を使うと、同じ反復処理を簡潔に表せます。

lists = [[1, 2, 3], [4, 5], [6, 7]]
combined = [item for current in lists for item in current]

どちらの方法でも新しいリストが作られます。手順を説明したり追加のロジックを入れたりする場合はループを、単純に要素を平坦化する場合はリスト内包表記を使うとよいでしょう。

各方法を比較して選ぶ

方法 入力を変更するか 結果 複数のリストに対応するか
+ いいえ 新しいリスト はい
extend() はい、追加先のリスト 呼び出しの戻り値は None 入力リストごとに呼び出す
+= はい、左辺のリスト 左辺のリストをその場で変更 入力リストごとに適用する
アンパック いいえ 新しいリスト はい
itertools.chain() いいえ イテレーター はい
ループまたは内包表記 いいえ 新しいリスト はい

読みやすい新しいリストを作るなら + またはアンパックを、既存のリストを拡張するなら extend() または += を使います。次の処理でイテレーターを使える場合は itertools.chain() を選びましょう。後続のコードでインデックス参照やリストのメソッドが必要なら、list() でリストに変換します。各方法ではメモリ確保や変更のされ方が異なりますが、どの入力サイズや処理内容にも当てはまる性能の順位はありません。実行時間やメモリ使用量が判断材料になる場合は、実際の用途に近いデータで測定してください。

まとめ

Python で2つ以上のリストを扱う場合、新しいリストを作るには + またはアンパックを、追加先のリストを変更するには extend() または += を使います。要素を遅延評価で反復するなら itertools.chain() が使えます。周囲のコードに合う場合は、ループや内包表記で新しい平坦なリストを作る方法もあります。