【问题标题】:Counting the number of True Booleans in a Python List计算 Python 列表中真正布尔值的数量
【发布时间】:2012-09-27 18:22:36
【问题描述】:

我有一个布尔值列表:

[True, True, False, False, False, True]

我正在寻找一种方法来计算列表中True 的数量(因此在上面的示例中,我希望返回为3。)我找到了查找出现次数的示例特定元素,但是由于我正在使用布尔值,有没有更有效的方法来做到这一点?我正在考虑类似于allany 的东西。

【问题讨论】:

    标签: python list boolean counting


    【解决方案1】:

    list 有一个count 方法:

    >>> [True,True,False].count(True)
    2
    

    这实际上比sum 更有效,而且意图更明确,因此没有理由使用sum

    In [1]: import random
    
    In [2]: x = [random.choice([True, False]) for i in range(100)]
    
    In [3]: %timeit x.count(True)
    970 ns ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    
    In [4]: %timeit sum(x)
    1.72 µs ± 161 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    

    【讨论】:

    • 如果还有 0 值,我就无法计算 False 值
    • 如果您有除 1 或 True 之外的其他“真”值,则不能使用其他答案的 sum。此外,然后问题除了TrueFalse之外没有提到任何内容。
    • 虽然不是 OP 的意图,但我认为值得指出的是 sum 适用于其他类型(例如生成器),而 count 不适用。
    【解决方案2】:

    看完这个问题的所有答案和cmets后,我想做一个小实验。

    我生成了 50,000 个随机布尔值,并在它们上调用了 sumcount

    这是我的结果:

    >>> a = [bool(random.getrandbits(1)) for x in range(50000)]
    >>> len(a)
    50000
    >>> a.count(False)
    24884
    >>> a.count(True)
    25116
    >>> def count_it(a):
    ...   curr = time.time()
    ...   counting = a.count(True)
    ...   print("Count it = " + str(time.time() - curr))
    ...   return counting
    ... 
    >>> def sum_it(a):
    ...   curr = time.time()
    ...   counting = sum(a)
    ...   print("Sum it = " + str(time.time() - curr))
    ...   return counting
    ... 
    >>> count_it(a)
    Count it = 0.00121307373046875
    25015
    >>> sum_it(a)
    Sum it = 0.004102230072021484
    25015
    

    为了确定,我又重复了几次:

    >>> count_it(a)
    Count it = 0.0013530254364013672
    25015
    >>> count_it(a)
    Count it = 0.0014507770538330078
    25015
    >>> count_it(a)
    Count it = 0.0013344287872314453
    25015
    >>> sum_it(a)
    Sum it = 0.003480195999145508
    25015
    >>> sum_it(a)
    Sum it = 0.0035257339477539062
    25015
    >>> sum_it(a)
    Sum it = 0.003350496292114258
    25015
    >>> sum_it(a)
    Sum it = 0.003744363784790039
    25015
    

    如您所见,countsum 快 3 倍。所以我建议像在count_it 中那样使用count

    Python 版本:3.6.7
    CPU 核心数:4
    内存大小:16 GB
    操作系统:Ubuntu 18.04.1 LTS

    【讨论】:

      【解决方案3】:

      为了完整起见(sum 通常更可取),我想提一下,我们也可以使用filter 来获取真实值。在通常情况下,filter 接受一个函数作为第一个参数,但如果你将它传递给None,它将过滤所有“真实”值。这个特性有点令人惊讶,但有据可查,并且在 Python 2 和 3 中都可以使用。

      版本之间的区别在于,在 Python 2 中filter 返回一个列表,所以我们可以使用len

      >>> bool_list = [True, True, False, False, False, True]
      >>> filter(None, bool_list)
      [True, True, True]
      >>> len(filter(None, bool_list))
      3
      

      但是在 Python 3 中,filter 返回一个迭代器,所以我们不能使用 len,如果我们想避免使用 sum(出于任何原因),我们需要将迭代器转换为列表(这让这变得不那么漂亮了):

      >>> bool_list = [True, True, False, False, False, True]
      >>> filter(None, bool_list)
      <builtins.filter at 0x7f64feba5710>
      >>> list(filter(None, bool_list))
      [True, True, True]
      >>> len(list(filter(None, bool_list)))
      3
      

      【讨论】:

        【解决方案4】:

        先跑bool比较安全。这很容易做到:

        >>> sum(map(bool,[True, True, False, False, False, True]))
        3
        

        然后,您会将 Python 认为是真或假的所有内容捕获到适当的存储桶中:

        >>> allTrue=[True, not False, True+1,'0', ' ', 1, [0], {0:0}, set([0])]
        >>> list(map(bool,allTrue))
        [True, True, True, True, True, True, True, True, True]
        

        如果您愿意,可以使用推导式:

        >>> allFalse=['',[],{},False,0,set(),(), not True, True-1]
        >>> [bool(i) for i in allFalse]
        [False, False, False, False, False, False, False, False, False]
        

        【讨论】:

          【解决方案5】:

          我更喜欢len([b for b in boollist if b is True])(或生成器表达式等价物),因为它是不言自明的。没有 Ignacio Vazquez-Abrams 提出的答案那么“神奇”。

          或者,您可以这样做,它仍然假设 bool 可转换为 int,但不对 True 的值做任何假设: ntrue = sum(boollist) / int(True)

          【讨论】:

          • 您的解决方案至少有两个问题。一,它遭受同样的鲁棒性问题;您可以通过将测试更改为if b 来解决。但是,更重要的是,您正在构建一个一次性列表,要求所有值一次都在内存中,并且您不能将 len 与生成器表达式一起使用。最好避免此类做法,以便解决方案可以扩展。
          • @Ned Deily :if b 完全错误。只有当问题是关于评估为 True 的项目而不是实际的 True 布尔值时,它才是正确的。我同意你的第二点。在这种情况下,有变体sum(1 if b is True else 0 for b in boollist)
          • 正如我在其他地方指出的那样,我不清楚 OP 是否真的意味着只计算值为 1 的 bool 类型的对象,还是意味着更大且通常更有用的一组评估值真的。如果是前者,那么身份测试是正确的方法,但它也有限制。无论如何,bool 类型的对象在 Python 中是相当奇怪的鸭子,这是该语言相对较新的添加。无论如何,我会选择更简单的:sum(1 for b in boollist if b is True)
          【解决方案6】:

          如果你只关心常量True,一个简单的sum 就可以了。但是,请记住,在 Python 中,其他值也评估为 True。更强大的解决方案是使用 bool 内置:

          >>> l = [1, 2, True, False]
          >>> sum(bool(x) for x in l)
          3
          

          更新:这是另一个同样强大的解决方案,具有更透明的优势:

          >>> sum(1 for x in l if x)
          3
          

          附: Python 琐事:True 可能为真而不为 1。警告:不要在工作中尝试这个!

          >>> True = 2
          >>> if True: print('true')
          ... 
          true
          >>> l = [True, True, False, True]
          >>> sum(l)
          6
          >>> sum(bool(x) for x in l)
          3
          >>> sum(1 for x in l if x)
          3
          

          更邪恶:

          True = False
          

          【讨论】:

          • 好的,我看到了你的例子,我看到了它在做什么。除了它的 LOL 性之外,真的有充分的理由去做你在这里展示的事情吗?
          • 是的,对于顶部。正如我所指出的,“真”的 Python 测试(如在if 语句中)比仅测试True 更复杂。见docs.python.org/py3k/library/stdtypes.html#truthTrue = 2 只是为了强调“真实”的概念更复杂;使用一点额外代码(即使用bool()),您可以使解决方案更健壮、更通用。
          • 在 Python 3 中,TrueFalse 是关键字,您无法更改它们。
          【解决方案7】:

          你可以使用sum():

          >>> sum([True, True, False, False, False, True])
          3
          

          【讨论】:

            【解决方案8】:

            True 等于 1

            >>> sum([True, True, False, False, False, True])
            3
            

            【讨论】:

            • 这不是惯用的,并且会“滥用” bool 的类型强制。
            • @Jan Segre,没有强制,bool 是整数类型。
            • @panda-34,我检查了,issubclass(bool, int) 实际上成立,所以没有强制。
            猜你喜欢
            • 2016-04-08
            • 1970-01-01
            • 2013-05-01
            • 2017-01-02
            • 2023-04-02
            • 2016-09-28
            • 2021-07-18
            • 2014-08-14
            • 2012-07-28
            相关资源
            最近更新 更多