I'm looking for an iterator preferably from itertools or more_itertools that groups my_list
such that each group starts at the first even digit that follows after an odd digit (or has no predecessor).
The single yielded groups shall also contain the odd digits trailing after 1 or multiple even digits.
is_even = lambda x: x % 2 == 0
my_list = [2, 8, 7, 6, 4, 2, 4, 5, 3, 4, 1, 2]
# is_even:[t, t, f, t, t, t, t, f, f, t, f, t] # t = true, f = false
# needles:
for group in magic_iterator(my_list, is_even):
sub_list = list(group)
# expected results:
# first sub_list: [2,8,7]
# second sub_list:[6,4,2,4,5,3]
# third sub_list: [4,1]
# fourth sub_list:[2]
I'm optimistic that there is a suitable iterator in more_itertools and I don't have to write it myself (see below) but I cannot find it.
I already tried partition but that splits my list into only two distinct sub groups. I also tried for _, group in groupby(my_list, key=is_even)
with the usual groupby from itertools but it splits even and odd digits leading to ~twice as many groups as expected.
Code with similar result, but ugly
I came up with some dirty code that leads the expected result for comparison:
from itertools import groupby
from typing import List
result: List[List[int]] = []
last_group_has_been_added = False
for group_key, group in groupby(my_list, key=is_even):
sub_list = list(group)
if group_key is True:
sub_group = sub_list
last_group_has_been_added = False
else:
try:
sub_group += sub_list
except NameError: # name 'sub_group' is not defined
# occurs if the first item in my list is odd
sub_group = sub_list
result.append(sub_group)
last_group_has_been_added = True
if not last_group_has_been_added:
result.append(sub_list)
but that's not very pretty; I'm looking for a one-line solution ideally ;)
The more_itertool you're looking for is split_when:
Prints as expected:
[2, 8, 7]
[6, 4, 2, 4, 5, 3]
[4, 1]
[2]
It also works if first item is odd.