Pythonで配列をflattenする方法を解説

Python

本記事では、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する方法はいくつかあります:

  1. 2次元配列の場合:
    • forループ
    • リスト内包表記
    • itertools.chain
    • sumメソッド
    • numpy.flatten(同じ長さの配列の場合)
  2. 多次元配列の場合:
    • 再帰関数
    • functools.reduce

用途に合わせて最適な方法を選びましょう。小〜中規模のデータにはリスト内包表記、大規模データにはitertools.chain、多次元データには再帰関数が推奨されます。

タイトルとURLをコピーしました