単調増加の数列を、連続する値毎にまとめる簡潔な記述方法があったのでメモしておきます。
import itertools
sample = [1,2,3,5,6,7,9,10]
[list(g) for _, g in itertools.groupby(
sample, key=lambda n, c=itertools.count(): n - next(c))]
# => [[1, 2, 3], [5, 6, 7], [9, 10]]
itertools.groupby
は、第一引数のイテラブルの各要素を第二引数に渡して、その戻り値が同一の連続する要素を返すイテレータを、第二引数の関数に渡した要素とともに返します。
上の例では、第一引数にsample
、第二引数key
にラムダ式をとっています。
ラムダ式には、n
と、省略可能なc
の二つの引数がありますが、c
にはitertools.count()
のデフォルト値が指定されており、groupby
における連続する要素の同一性の判定の際に呼ばれる時は、n
にsample
の各要素が渡されます。itertools.count()
は、0
から1
ずつ増加する数を返すイテレータを生成します。c
のデフォルト値はラムダ式が定義されたときに一回だけ実行され、0から順に+1
された数を返すイテレータが代入されます。ですので、n - next(c)
は、next(c)
は毎回の呼び出しで1
ずつ増加するので、n
が1
づつ増加すれこのラムダ式からは同じ値が返されますが、n
が1
より大きく増加すれば違う値が返されます。このラムダ式の戻り値が同一の連続する要素を返すイテレータがg
で、list(g)
により、連続した要素をネストしたリストにまとめたリストがリスト内包表記により生成されます。