I am just wondering how the list could be rearranged into list of list with a series of incremental integers as list element. For example, let's imagine that I have a list as follows:
example = [2, 43, 44, 64, 143, 144, 145, 146, 147, 148, 178, 179, 180, 181, 182, 183, 184, 211]
And I would like to convert this list into the one as follows:
converted_example = [[2], [43, 44], [64], [143, 144, 145, 146, 147, 148], [178, 179, 180, 181, 182, 183, 184], [211]]
Do you have any ideas on this? Thanks in advance!
CodePudding user response:
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]]
Each call of groupby_adjacent()
will produce a new version of f
with its own set of unique local variables, and the returned f
can then be passed to a single .groupby()
function. I used a dict to store variables instead of actually using variables because I wanted to avoid using the global
keyword (it can have behavior reaching beyond where you might intend it to).
The call to sorted()
can, of course, be omitted if you can guarantee that example
will already be sorted.