本記事では、Pythonで配列をflattenする方法を解説します。falttenする方法はいくつかありその中でも主要な方法を説明します。
flattenとは
flattenする方法の前に言葉の説明をします。flattenとは2次元以上の配列を1次元の配列に変換することを言います。
変換例
ネストされた配列
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flatten後
flattened = [1, 2, 3, 4, 5, 6, 7, 8, 9]
flattenする方法
flattenする配列が2次元配列かそれ以上の次元かで方法が異なります。
2次元配列
forループを使う方法
シンプルな二重ループでネストした配列の各要素にアクセスします。外側のループでサブリストを取得し、内側のループで各サブリストの要素を新しいリストに追加します。
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flattened = []
for sublist in nested:
for item in sublist:
flattened.append(item)
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
リスト内包表記を使う方法
Pythonのリスト内包表記を使うと、コードが簡潔になります。二重のforループを一行で表現できます。内側のループが外側のループの中に入れ子になっている点に注意してください。
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flattened = [item for sublist in nested for item in sublist]
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
itertools.chainを使う方法
Pythonの標準ライブラリitertoolsのchain関数を使うと、複数のイテラブルを一つのイテラブルに連結できます。アスタリスク(*)演算子でネストリストをアンパックし、各サブリストを個別の引数として渡します。
import itertools
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flattened = list(itertools.chain(*nested))
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
sumを使う方法
sum関数の第二引数に空リストを指定すると、リストの連結として機能します。この方法はシンプルですが、大きなリストの場合はパフォーマンスが低下する可能性があります。
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flattened = sum(nested, [])
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
numpy.flattenを使う方法
NumPyライブラリのflatten関数を使うと、多次元配列を1次元に変換できます。ただし、NumPy配列は同じ長さのサブリストのみ対応しているため、不均一な長さのリストでは使えません。
import numpy as np
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
# numpy配列は同じ長さの配列のみ対応するため、この例ではエラーになります
# 以下は同じ長さの場合の例
same_length = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = np.array(same_length).flatten().tolist()
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
2次元配列でどの方法がよいのか
実用的なシナリオでは、リスト内包表記はコード量と速度のバランスが取れており、追加のインポートが不要なため多くの場合に適しています。itertools.chainはさらに速度とメモリ効率が必要な場合に最適です。処理するデータが数百万要素を超えるような大規模なリストでは、itertools.chainの効率性が顕著になります。
任意の次元の配列
再帰関数を使う方法
再帰を使うと、どんな深さのネストされたリストも平坦化できます。各要素がリスト型かどうかをチェックし、リストならさらに再帰的に平坦化し、そうでなければ結果に追加します。
def flatten_recursive(nested_list):
flattened = []
for item in nested_list:
if isinstance(item, list):
flattened.extend(flatten_recursive(item))
else:
flattened.append(item)
return flattened
nested = [1, [2, [3, 4]], [5, 6, [7, 8, 9]]]
flattened = flatten_recursive(nested)
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
functools.reduceを使う方法
functools.reduceとoperator.addを組み合わせると、リストを効率的に結合できます。この方法は関数型プログラミングのアプローチで、再帰と組み合わせて任意の深さのリストを平坦化します。
import functools
import operator
def flatten_reduce(nested_list):
if not nested_list:
return []
if isinstance(nested_list[0], list):
return functools.reduce(operator.add, [flatten_reduce(item) if isinstance(item, list) else [item] for item in nested_list])
return [nested_list[0]] + flatten_reduce(nested_list[1:])
nested = [1, [2, [3, 4]], [5, 6, [7, 8, 9]]]
flattened = flatten_reduce(nested)
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
まとめ
Pythonで配列をflattenする方法はいくつかあります:
- 2次元配列の場合:
- forループ
- リスト内包表記
- itertools.chain
- sumメソッド
- numpy.flatten(同じ長さの配列の場合)
- 多次元配列の場合:
- 再帰関数
- functools.reduce
用途に合わせて最適な方法を選びましょう。小〜中規模のデータにはリスト内包表記、大規模データにはitertools.chain、多次元データには再帰関数が推奨されます。