import itertools
def groupby_adjacent(max_step_size=1):
# generate a persistent function that tracks successive calls,
# to feed to itertools.groupby
# (assume the input is already sorted)
v = {
'last': None, # last value encountered
'group': 0 # value to return for groupby
}
def f(current):
# if the current element exceeds the last element by more than one,
# break the groupby and start a new group
if v['last'] is not None and current - max_step_size > v['last']:
v['group'] = v['group'] + 1
# otherwise, just keep the same group as we currently have
v['last'] = current
return v['group']
return f
example = [2, 43, 44, 64, 143, 144, 145, 146, 147, 148, 178, 179, 180, 181, 182, 183, 184, 211]
converted_example = [list(tup[1]) for tup in
itertools.groupby(sorted(example), key=groupby_adjacent())
]
# [[2], [43, 44], [64], [143, 144, 145, 146, 147, 148], [178, 179, 180, 181, 182, 183, 184], [211]]
groupby_adjacent() 的每次调用都会产生一个新版本的f,它有自己独特的局部变量集,然后可以将返回的f 传递给单个.groupby() 函数。我使用 dict 来存储变量而不是实际使用变量,因为我想避免使用 global 关键字(它的行为可能超出您的预期)。
如果您能保证example 已经被排序,当然可以省略对sorted() 的调用。