Đếm số lượng Booleans thật trong Danh sách Python


152

Tôi có một danh sách Booleans:

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

và tôi đang tìm cách để đếm số lượng Truetrong danh sách (vì vậy trong ví dụ trên, tôi muốn trả về 3.) Tôi đã tìm thấy các ví dụ về tìm kiếm số lần xuất hiện của các yếu tố cụ thể, nhưng có nhiều hơn không Cách hiệu quả để làm điều đó vì tôi đang làm việc với Booleans? Tôi đang nghĩ về một cái gì đó tương tự allhoặc any.


Giống như nếu bạn nhớ cách đếm bit được thực hiện trong phần cứng chỉ bằng cách sử dụng trình biên dịch chương trình.
Vladislavs Dovgalecs

Câu trả lời:


207

Truebằng 1.

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

23
Đó không phải là thành ngữ và làm cho "lạm dụng" kiểu ép buộc của bool.
Jan Segre

24
@Jan Segre, không có sự ép buộc, bool là một kiểu số nguyên.
panda-34

25
@ panda-34, tôi đã kiểm tra và issubclass(bool, int)trên thực tế giữ, vì vậy không có sự ép buộc nào.
Jan Segre

152

listcó một countphương pháp:

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

Điều này thực sự hiệu quả hơn sum, cũng như rõ ràng hơn về ý định, vì vậy không có lý do để sử dụng 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)

2
Tôi không thể đếm các giá trị Sai nếu cũng có 0 giá trị
Kostanos

10
Bạn không thể sử dụng sumcâu trả lời khác nếu bạn có các giá trị "đúng" khác ngoài 1 hoặc Đúng. Bên cạnh đó, sau đó câu hỏi không đề cập đến bất cứ điều gì nhưng Truehay False.
Đánh dấu Tolonen

43

Nếu bạn chỉ quan tâm đến hằng số True, một đơn giản sumlà tốt. Tuy nhiên, hãy nhớ rằng trong Python cũng có các giá trị khác True. Một giải pháp mạnh mẽ hơn sẽ là sử dụng boolnội dung:

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

CẬP NHẬT: Đây là một giải pháp mạnh mẽ tương tự khác có ưu điểm là minh bạch hơn:

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

PS Trivia: True thể đúng mà không cần 1. Cảnh báo: đừng thử điều này tại nơi làm việc!

>>> 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

Tội ác hơn nhiều:

True = False

Ok, tôi thấy ví dụ của bạn, và tôi thấy những gì nó đang làm. Ngoài tính chất LOL của nó, có thực sự có lý do để làm những gì bạn đã thể hiện ở đây không?
acs

1
Vâng, cho phần đầu. Như tôi đã chỉ ra, kiểm tra Python cho "true" (như trong một iftuyên bố) phức tạp hơn so với chỉ kiểm tra True. Xem docs.python.org/py3k/l Library / stdtypes.html#truth . Điều True = 2này chỉ để củng cố rằng khái niệm "đúng" phức tạp hơn; với một chút mã bổ sung (nghĩa là sử dụng bool()), bạn có thể làm cho giải pháp mạnh mẽ hơn và tổng quát hơn.
Ned Deily

9
Trong Python 3, TrueFalselà các từ khóa và bạn không thể thay đổi chúng.
ThePiercingPrince

8

Bạn có thể sử dụng sum():

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

5

Chỉ vì sự hoàn chỉnh ( sumthường là thích hợp hơn), tôi muốn đề cập rằng chúng ta cũng có thể sử dụng filterđể có được các giá trị trung thực. Trong trường hợp thông thường, filterchấp nhận một hàm làm đối số đầu tiên, nhưng nếu bạn vượt qua nóNone , nó sẽ lọc tất cả các giá trị "trung thực". Tính năng này có phần đáng ngạc nhiên, nhưng được ghi lại tốt và hoạt động trong cả Python 2 và 3.

Sự khác biệt giữa các phiên bản là trong Python 2 filtertrả về một danh sách, vì vậy chúng ta có thể sử dụng len:

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

Nhưng trong Python 3, filtertrả về một trình vòng lặp, vì vậy chúng ta không thể sử dụng lenvà nếu chúng ta muốn tránh sử dụng sum(vì bất kỳ lý do nào), chúng ta cần phải sử dụng để chuyển đổi trình lặp thành một danh sách (điều này làm cho nó ít đẹp hơn):

>>> 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

Sau khi đọc tất cả các câu trả lời và nhận xét về câu hỏi này, tôi nghĩ sẽ làm một thí nghiệm nhỏ.

Tôi đã tạo ra 50.000 booleans ngẫu nhiên và gọi sumcount trên chúng.

Đây là kết quả của tôi:

>>> 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

Để chắc chắn, tôi lặp lại nó nhiều lần:

>>> 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

Và như bạn thấy, countnhanh hơn 3 lần sum. Vì vậy, tôi sẽ đề nghị sử dụng countnhư tôi đã làm trongcount_it .

Phiên bản Python: 3.6.7
lõi CPU: 4
RAM Kích thước: 16 GB
Hệ điều hành: Ubuntu 18.04.1 LTS


3

Nó là an toàn hơn để chạy qua boolđầu tiên. Điều này được thực hiện dễ dàng:

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

Sau đó, bạn sẽ bắt mọi thứ mà Python coi là Đúng hoặc Sai vào nhóm thích hợp:

>>> 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]

Nếu bạn thích, bạn có thể sử dụng một sự hiểu biết:

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

1

Tôi thích len([b for b in boollist if b is True])(hoặc tương đương với biểu thức của trình tạo), vì nó khá tự giải thích. Ít 'ma thuật' hơn câu trả lời được đề xuất bởi Ignacio Vazquez-Abrams.

Ngoài ra, bạn có thể làm điều này, điều này vẫn cho rằng bool có thể chuyển đổi thành int, nhưng không đưa ra giả định nào về giá trị của True: ntrue = sum(boollist) / int(True)


Giải pháp của bạn có ít nhất hai vấn đề. Một, nó bị vấn đề mạnh mẽ tương tự; mà bạn có thể khắc phục bằng cách thay đổi thử nghiệm thành if b. Nhưng, quan trọng hơn, bạn đang xây dựng một danh sách vứt bỏ yêu cầu tất cả các giá trị phải có trong bộ nhớ cùng một lúc và bạn không thể sử dụng lenvới biểu thức trình tạo. Tốt hơn để tránh thực hành như vậy để giải pháp có thể mở rộng.
Ned Deily

@Ned Deily: if bchính xác là sai. Nó sẽ chỉ đúng nếu câu hỏi là về các mục đánh giá là True, chứ không phải là booleans True thực sự. Tôi lấy điểm thứ hai của bạn mặc dù. Trong trường hợp đó có biến thể sum(1 if b is True else 0 for b in boollist).
kampu

Như tôi đã lưu ý ở nơi khác, tôi không rõ câu hỏi liệu OP thực sự có nghĩa là chỉ đếm các đối tượng thuộc loại bool có giá trị 1 hay có nghĩa là tập hợp các giá trị lớn hơn và thường hữu ích hơn để đánh giá đúng. Nếu trước đây, thì một bài kiểm tra danh tính là cách tiếp cận đúng nhưng nó cũng hạn chế. Các đối tượng của kiểu bool là những con vịt khá kỳ quặc trong Python, một sự bổ sung tương đối gần đây vào ngôn ngữ. Trong mọi trường hợp, tôi sẽ đơn giản hơn:sum(1 for b in boollist if b is True)
Ned Deily
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.