聪明any()之类的函数检查至少n个元素是否为True?

时间:2017-02-28 16:52:42

标签: python python-3.x built-in

说我有一个可迭代的(在我的例子中是一个列表):

l = [True, False, False, True]

我知道检查其中至少有一个元素是否为True的最简单快捷的方法就是使用any(l),这将返回True

但是如果我想检查至少两个元素是True怎么办? 我的目标是以最快的方式处理它。

我的代码现在看起来像这样(对于两个元素):

def check_filter(l):
    if len([i for i in filter(None, l)]) > 1:
        return True
return False

这比any()慢大约10倍,而且对我来说似乎不是那么pythonic。

4 个答案:

答案 0 :(得分:12)

你可以简单地在序列上使用迭代器,并检查迭代器上的imageView总是为any返回True - 次:

n

这里的关键点是迭代器会记住它最后的位置,因此每个def check(it, num): it = iter(it) return all(any(it) for _ in range(num)) >>> check([1, 1, 0], 2) True >>> check([1, 1, 0], 3) False 调用将从最后一个调用开始。并将其包裹在any中,一旦all any False,就确保它会提前退出。

至少在性能方面,这应该比大多数其他方法更快。但是以可读性为代价。

如果您想让它比基于mapitertools.repeat的解决方案更快,可以稍快一点:

from itertools import repeat

def check_map(it, num):
    return all(map(any, repeat(iter(it), num)))

对其他答案进行基准测试:

# Second "True" element is in the last place
lst = [1] + [0]*1000 + [1]

%timeit check_map(lst, 2)  # 10000 loops, best of 3: 20.3 µs per loop
%timeit check(lst, 2)      # 10000 loops, best of 3: 23.5 µs per loop
%timeit many(lst, 2)       # 10000 loops, best of 3: 153 µs per loop
%timeit sum(l) >= 2        # 100000 loops, best of 3: 19.6 µs per loop

# Second "True" element is the second item in the iterable
lst = [1, 1] + [0]*1000

%timeit check_map(lst, 2)  # 100000 loops, best of 3: 3.05 µs per loop
%timeit check(lst, 2)      # 100000 loops, best of 3: 6.39 µs per loop
%timeit many(lst, 2)       # 100000 loops, best of 3: 5.02 µs per loop
%timeit sum(lst) >= 2      # 10000 loops, best of 3: 19.5 µs per loop

答案 1 :(得分:4)

L = [True, False, False, True]

这只需要迭代:

def many(iterable, n):
    if n < 1:
        return True
    counter = 0
    for x in iterable:
        if x:
            counter += 1
            if counter == n:
                return True
    return False

现在:

>>> many(L, 2)
True

答案 2 :(得分:1)

使用sum

sum(l) >= 2
# True

答案 3 :(得分:0)

大概any遍历迭代,直到找到True的元素,然后停止。

您的解决方案扫描所有元素以查看是否至少有2个。相反,它应该在找到第二个True元素后立即停止扫描。