有没有一种方法可以根据条件“分叉”成两个列表

时间:2018-08-08 09:08:17

标签: python list

我在我的团队的代码中看到了重复几次的模式,看起来像这样

numbers = [1, 2, 3, 4]
even_numbers = [n for n in numbers if n % 2 == 0]
odd_numbers = [n for n in numbers if n % 2 != 0]

我想知道某个地方是否有某个功能(我环顾四周,但是找不到)

numbers = [1, 2, 3, 4]
even_numbers, odd_numbers = fork(numbers, lambda x: x % 2 == 0)

因此,我正在寻找的该函数将收到一个可迭代的函数,并返回两个列表,一个列表将是与提供的条件匹配的值,另一个列表是不符合条件的值。

python的标准库周围是否有实现这一目标的东西?

5 个答案:

答案 0 :(得分:11)

我通常将其称为sift,但是partition也可以。

另一种无需itertools的实现方式

def sift(iterable, predicate):
    t = []
    f = []
    for value in iterable:
        (t if predicate(value) else f).append(value)
    return (t, f)

even, odd = sift([1, 2, 3, 4, 5], lambda x: x % 2 == 0)

编辑:对于稍微复杂一点的实现,速度大约要快30%(无论如何在我的Python安装上):

def sift2(iterable, predicate):
    t = []
    f = []
    ta = t.append
    fa = f.append
    for value in iterable:
        (ta if predicate(value) else fa)(value)
    return (t, f)

答案 1 :(得分:3)

您可以使用以下功能:

from itertools import filterfalse, tee

def fork(pred, iterable):
    'Use a predicate to partition entries into false entries and true entries'
    t1, t2 = tee(iterable)
    return list(filterfalse(pred, t1)), list(filter(pred, t2))

来源:itertools

答案 2 :(得分:2)

@jonrsharpe建议后的完整代码。

import itertools

def fork(iterable):
    "Returns list of even, odd elements of a list"
    t1, t2 = itertools.tee(iterable)
    pred = lambda i: i % 2 == 0
    return list(filter(pred, t2)), list(itertools.filterfalse(pred, t1))

odd, even = fork([1,2,3,4,5])
print(odd)
print(even)

替代的numpy版本,对于大型数组而言可能更快

import numpy as np

def fork(iterable):
    "Returns array of even, odd elements of an array"
    iterable_array = np.asarray(iterable)
    mask = (iterable_array % 2 == 0)
    return iterable_array[~mask], iterable_array[mask]

答案 3 :(得分:2)

我没有在标准库中找到满足您要求的任何内容。我建议您使用这个用户定义的实现,它根本没有优化,但是非常简单易读:

def myFunc(iterable, func):

    first  = [i for i in iterable if func(i)]
    second = [i for i in iterable if not func(i)]

    return first,second


numbers = [1, 2, 3, 4]
even_numbers, odd_numbers = myFunc(numbers, lambda x: x % 2 == 0)

print(even_numbers) # [2, 4]
print(odd_numbers)  # [1, 3]

答案 4 :(得分:0)

您可以创建自己的函数:

l = [1, 2, 3, 4]
def fork(l,key):
   return list(filter(key,l)), [i for i in l if i not in list(filter(key,l))]
even_numbers, odd_numbers = fork(l, lambda x: x % 2 == 0)
print(even_numbers)
print(odd_numbers)

输出:

[2, 4]
[1, 3]