This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: separate builtin function
Type: enhancement Stage:
Components: Versions: Python 3.10
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: alvarezdqal, ammar2, rhettinger, serhiy.storchaka
Priority: normal Keywords:

Created on 2021-04-20 21:47 by alvarezdqal, last changed 2022-04-11 14:59 by admin.

Messages (4)
msg391479 - (view) Author: David Alvarez Lombardi (alvarezdqal) Date: 2021-04-20 21:47
I frequently find myself doing the following for lists, sets, and dicts.

````
passes = [x for x in seq if cond(x)]
fails = [x for x in seq if not cond(x)]
````

The proposed function would behave similarly to `filter`, but it would return a tuple of the passes iterable and fails iterable rather than just the passes.

````
my_list = [-3, -2, -1, 0, 1, 2, 3]
def is_positive(n):
    return n > 0

positives, negatives = separate(function=is_positive, iterable=my_list)
````
msg391484 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2021-04-20 22:57
FWIW, here's a recipe from the itertools docs:

    def partition(pred, iterable):
        "Use a predicate to partition entries into false entries and true entries"
        # partition(is_odd, range(10)) --> 0 2 4 6 8   and  1 3 5 7 9
        t1, t2 = tee(iterable)
        return filterfalse(pred, t1), filter(pred, t2)


Also, here's a more general solution that can handle multiple categories:

    >>> from collections import defaultdict
    >>> def categorize(func, iterable):
            d = defaultdict(list)
            for x in iterable:
                d[func(x)].append(x)
            return dict(d)

    >>> categorize(is_positive, [-3, -2, -1, 0, 1, 2, 3])
    {False: [-3, -2, -1, 0], True: [1, 2, 3]}
    >>> categorize(lambda x: x%3, [-3, -2, -1, 0, 1, 2, 3])
    {0: [-3, 0, 3], 1: [-2, 1], 2: [-1, 2]}


At one point, Peter Norvig suggested adding a groupby classmethod to dictionaries.  I would support that idea.   Something like:

    dict.groupby(attrgetter('country'), conferences)
msg391494 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-04-21 07:02
The drawback of that recipe of partition() is that it calls predicate twice on every element. The following implementation calls it only once for every element:

    def partition(pred, iterable):
        t1, t2 = tee((bool(pred(x)), x) for x in iterable)
        return (x for p, x in t1 if not p), (x for p, x in t1 if p)

but it may be less efficient for fast predicates.
msg392320 - (view) Author: Ammar Askar (ammar2) * (Python committer) Date: 2021-04-29 15:31
Note that the `more_itertools` package on pypi also has a partition method.

Shall we close this off given that a recipe is already present and this is available as part of a popular 3rd-party library?
History
Date User Action Args
2022-04-11 14:59:44adminsetgithub: 88065
2021-04-29 15:31:13ammar2setnosy: + ammar2
messages: + msg392320
2021-04-21 07:02:32serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg391494
2021-04-20 22:57:43rhettingersetnosy: + rhettinger
messages: + msg391484
2021-04-20 21:47:05alvarezdqalcreate