简体   繁体   中英

python equivalent of scala partition

I'm currently porting some Scala code to Python and I am wondering what is the most pythonic way to do something similar to Scala's partition ? In particular, in the Scala code I have a situation where I am partitioning a list of items based on whether they return true or false from some filter predicate that I pass in:

val (inGroup,outGroup) = items.partition(filter)

What is the best way to do something like this in Python?

Using filter (require two iteration):

>>> items = [1,2,3,4,5]
>>> inGroup = filter(is_even, items) # list(filter(is_even, items)) in Python 3.x
>>> outGroup = filter(lambda n: not is_even(n), items)
>>> inGroup
[2, 4]
>>> outGroup

Simple loop:

def partition(item, filter_):
    inGroup, outGroup = [], []
    for n in items:
        if filter_(n):
            inGroup.append(n)
        else:
            outGroup.append(n)
    return inGroup, outGroup

Example:

>>> items = [1,2,3,4,5]
>>> inGroup, outGroup = partition(items, is_even)
>>> inGroup
[2, 4]
>>> outGroup
[1, 3, 5]

Scala

val (inGroup,outGroup) = items.partition(filter)

Python - Using List Comprehension

inGroup = [e for e in items if _filter(e)]
outGroup = [e for e in items if not _filter(e)]

This version is lazy and doesn't apply the predicate twice to the same element:

def partition(it, pred):
    buf = [[], []]
    it = iter(it)

    def get(t):
        while True:
            while buf[t]:
                yield buf[t].pop(0)
            x = next(it)
            if t == bool(pred(x)):
                yield x
            else:
                buf[not t].append(x)

    return get(True), get(False)

Example:

even = lambda x: x % 2 == 0

e, o = partition([1,1,1,2,2,2,1,2], even)
print list(e)
print list(o)

Scala has rich list processing api, and Python is much as that.

You should read document itertools . And you may find a receipe of partition.

from itertools import ifilterfalse, ifilter, islice, tee, count

def partition(pred, iterable):
    '''
    >>> is_even = lambda i: i % 2 == 0
    >>> even, no_even = partition(is_even, xrange(11))
    >>> list(even)
    [0, 2, 4, 6, 8, 10]
    >>> list(no_even)
    [1, 3, 5, 7, 9]

    # Lazy evaluation
    >>> infi_list = count(0)
    >>> ingroup, outgroup = partition(is_even, infi_list)
    >>> list(islice(ingroup, 5))
    [0, 2, 4, 6, 8]
    >>> list(islice(outgroup, 5))
    [1, 3, 5, 7, 9]
    '''
    t1, t2 = tee(iterable)
    return ifilter(pred, t1), ifilterfalse(pred, t2)

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