如何像 "map "支持的那样,使用 "filter "与多个迭代符?

问题描述 投票:0回答:1

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个iterable,而不是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.

python python-3.x list iterable
1个回答
1
投票

怎么样。

def filter_(predicate, *iterables):
    for t in zip(*iterables):
        if predicate(*t):
            yield t

print(list(filter_(operator.eq, [1, 2, 3, 4], [1, 2, 2, 4])))

它是懒惰的,它输出 [(1, 1), (2, 2), (4, 4)] 为您的测试用例,不,您不能使用 ([1, 2, 4], [1, 2, 4]) 因此,以一种懒惰的方式。要从 [(1, 1), (2, 2), (4, 4)]([1, 2, 4], [1, 2, 4]) 你可以用。zip(*filter_(operator.eq, [1, 2, 3, 4], [1, 2, 2, 4])) 但这样一来,你就失去了懒惰的感觉。


2
投票

遗憾的是没有等价的 starmap 喜欢 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)))))

1
投票

你的答案在你的执行过程中。Map 接受一个函数,接受多个列表,而这些列表必须与参数的数量相匹配。Filter只接受一个列表来进行过滤,所以两者的区别不仅仅是语义上的--filter只接受一个列表是合理的。在你的例子中,列表确实是 zip这就是你要实现的。你缺少的是一个巧妙的方法来解除配对的结果。

>>> r1, r2 = zip(*filter(lambda x: predicate(*x), zip([1, 2, 3, 4, 5], [1, 1, 3, 3, 5)))
>>> r1
(1, 3, 5)
>>> r2
(1, 3, 5)
© www.soinside.com 2019 - 2024. All rights reserved.