简体   繁体   中英

python itertools groupby with filter usage

I have a list = [1, 2, 3, 3, 6, 8, 8, 10, 2, 5, 7, 7] I am trying to use groupby to convert it into

1
2
3
3
6
8,8
10
2,
5
7,7

Basically, anything greater then 6, I like to group them, otherwise I want to keep them ungrouped. Any hint on how I can do this with itertool groupby

My code currently:

for key, group in it.groupby(numbers, lambda x: x):
   f = list(group)
   if len(f) == 1:
      split_list.append(group[0])
   else:
      if (f[0] > 6):  #filter condition x>6
         for num in f: 
            split_list.append(num + 100)
       else:
         for num in f:
            split_list.append(num)

You can use itertools.groupby to group all elements greater than 6 and with groups of length greater than 1. All other elements remain ungrouped.

If we want groups as standalone lists, we can use append . If we want groups flattened, we can use extend .

from itertools import groupby

lst = [1, 2, 3, 3, 6, 8, 8, 10, 2, 5, 7, 7]

result = []
for k, g in groupby(lst):
    group = list(g)

    if k > 6 and len(group) > 1:
        result.append(group)
    else:
        result.extend(group)

print(result)

Output:

[1, 2, 3, 3, 6, [8, 8], 10, 2, 5, [7, 7]]

You can use flatten() function shown below. This function is modified version from https://stackoverflow.com/a/40857703/501852

The function below is a generator object ( python ver >= 3.8 ).

Added conditioning function as input parameter.

from typing import Iterable 

def flatten(items, cond_func=lambda x: True):
    """Yield items from any nested iterable"""
    for x in items:
        if isinstance(x, Iterable) \
                and not isinstance(x, (str, bytes)) \
                and cond_func(x):    # Conditioning function
            yield from flatten(x)
        else:
            yield x

Then you can use list comprehension variant:

res = flatten( [list(g) for k, g in groupby(lst)],
                cond_func = lambda x: x[0] <= 6 or len(x) == 1)
                 # Conditions to flatten

print(res)

And you can use generator variant:

res = flatten( (list(g) for k, g in groupby(lst)),
                cond_func = lambda x: x[0] <= 6 or len(x) == 1)
                 # Conditions to flatten

print(list(res))

Output is

[1, 2, 3, 3, 6, [8, 8], 10, 2, 5, [7, 7]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM