首页 > 解决方案 > 如何使用具有多个迭代的“filter”,如“map”支持的那样?

问题描述

filter只接受一个可迭代对象,而map接受可变数量的可迭代对象。例如,我可以用尽map(operator.add, [1, 2, 3, 4], [1, 2, 2, 4])全力得到[2, 4, 5, 8].

我正在寻找一种类似的机制filter,接受任何谓词和可变数量的迭代。用尽filter(operator.eq, [1, 2, 3, 4], [1, 2, 2, 4])导致TypeError关于如何filter只接受 1 个可迭代,而不是 2 个。

我对该特定情况的预期输出是([1, 2, 4], [1, 2, 4]),即不满足的成对元素operator.eq被删除。

这是我到目前为止所拥有的(急切的版本只支持 2 个迭代而不是 N):

from typing import TypeVar, Callable, Iterable

A = TypeVar("A")
B = TypeVar("B")

def filter_(predicate: Callable[[A, B], bool], iterable1: Iterable[A], iterable2: Iterable[B]) -> (Iterable[A], Iterable[B]):
    filtered_iterable1 = []
    filtered_iterable2 = []

    for value1, value2 in zip(iterable1, iterable2):
        if predicate(value1, value2):
            filtered_iterable1.append(value1)
            filtered_iterable2.append(value2)

    return filtered_iterable1, filtered_iterable2

然而,我的目标是 1)能够支持 N​​ 个可迭代对象和 2)filter_filter.

标签: pythonpython-3.xlistiterable

解决方案


不幸的是,没有等价于starmaplike starfilter,所以我能想到的等价物是:

[i for i in zip(*lists) if predicate(*i)]

lists这里是类似的东西([..], [..])。这导致:

[(1, 1), (2, 2), (4, 4)]

要将其转回单独的列表,请使用tuple(map(list, zip(*result)))

([1, 2, 4], [1, 2, 4])

所以,把它放在一起:

predicate = operator.eq
lists = [1, 2, 3, 4], [1, 2, 2, 4]

result = tuple(map(list, zip(*(i for i in zip(*lists) if predicate(*i)))))

推荐阅读