Ответ 1
True
равно 1
.
>>> sum([True, True, False, False, False, True])
3
У меня есть список Booleans:
[True, True, False, False, False, True]
и я ищу способ подсчитать количество True
в списке (поэтому в приведенном выше примере я хочу, чтобы return был 3
.) Я нашел примеры поиска количества вхождений конкретных элементов, но есть ли более эффективный способ сделать это, так как я работаю с Booleans? Я думаю о чем-то аналогичном all
или any
.
True
равно 1
.
>>> sum([True, True, False, False, False, True])
3
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)
Если вас интересует только константа True
, простая sum
в порядке. Однако имейте в виду, что в Python другие значения также оцениваются как True
. Более надежным решением было бы использовать встроенный bool
:
>>> l = [1, 2, True, False]
>>> sum(bool(x) for x in l)
3
UPDATE: здесь другое аналогичное надежное решение, имеющее преимущество более прозрачного:
>>> sum(1 for x in l if x)
3
P.S. Пустыни 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
Вы можете использовать sum()
:
>>> sum([True, True, False, False, False, True])
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
Вначале безопаснее проходить через bool
. Это легко сделать:
>>> sum(map(bool,[True, True, False, False, False, True]))
3
Затем вы поймаете все, что Python считает True или False в соответствующем ведре:
>>> 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]
Я предпочитаю len([b for b in boollist if b is True])
(или эквивалент генератора-выражения), так как он вполне объяснимо. Менее "магический", чем ответ, предложенный Игнасио Васкес-Абрамом.
В качестве альтернативы вы можете сделать это, что все еще предполагает, что bool можно преобразовать в int, но не делает никаких предположений о значении True:
ntrue = sum(boollist) / int(True)
Прочитав все ответы и комментарии по этому вопросу, я подумал сделать небольшой эксперимент.
Я сгенерировал 50 000 случайных логических чисел, назвал sum
и count
на них.
Вот мои результаты:
>>> 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
И, как вы можете видеть, count
в 3 раза быстрее, чем sum
. Поэтому я бы предложил использовать count
как я сделал в count_it
.
Версия Python: 3.6.7
Ядра процессора: 4
Объем оперативной памяти: 16 ГБ
ОС: Ubuntu 18.04.1 LTS