リストをN分割する

リストのデータをN個ずつ処理する場合等、N個ずつ分割したり、所定の数に分割しい場合がありますが、このページではそういったイディオムを紹介します。

Contents

リストをN個ずつの要素に分割する

要素数が10個のリストを3個の要素ずつ分割する場合について考えてみます。

一番簡単な方法として、3個の要素ずつスライスしてジェネレータで返す方法が考えられます。

def split_list(l, n):
    """
    リストをサブリストに分割する
    :param l: リスト
    :param n: サブリストの要素数
    :return: 
    """
    for idx in range(0, len(l), n):
        yield l[idx:idx + n]


l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = list(split_list(l, 3))
print(result) # [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

上の関数ですが、内部でfor文を回しているだけですので、内包表記に書き換えることができます。3分割する場合を内包表記で記述すると以下のとおりとなります。

l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
n = 3
result = [l[idx:idx + n] for idx in range(0,len(l), n)] # [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

やはり同じ結果を得ることができます。ワンライナーで書けてしまいますが少々可読性は落ちますので、繰り返し使用する場合は最初に紹介した関数を呼び出すようにしたほうがテストが楽だと思います。

リストをN分割する

リストをN分割する場合、numpyのarray_splitを使用する方法が一番楽だと思います。

例えば、要素数が10のリストを3分割する場合、以下のように記述します。

import numpy as np
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list(np.array_split(l, 3)) # [array([1, 2, 3, 4]), array([5, 6, 7]), array([ 8,  9, 10])]

ただし、注意点として文字列はarray_splitを使用できないので、注意してください。

numpyがインストールされていない環境や、文字列のようにarray_splitが使用できないシーケンスの場合は、以下のように最初紹介した方法に要素数の逆数を指定する方法を使用してみてください。

import math
text = "あいうえおかきくけこ"
n = math.ceil(len(text) / 3)
result = [ text[idx: idx + n] for idx in range(0,len(text), n)] # ['あいうえ', 'おかきく', 'けこ']

10文字の文字列を3分割することができました。逆数は切り上げている点に気をつけてください。

※ 2020/6/27 修正 サイトの不具合で上記コードの表示に一部欠損がありました。