Bir Python Listesindeki True Boolean sayısını sayma


162

Boole'ların bir listesi var:

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

ve Truelistedeki sayısını saymanın bir yolunu arıyorum (bu yüzden yukarıdaki örnekte, geri dönüşün olmasını istiyorum 3.) Belirli öğelerin oluşumlarının sayısını arama örnekleri buldum, ancak daha fazlası var mı? Booleans ile çalıştığım için bunu yapmanın verimli bir yolu var mı? allVeya benzeri bir şey düşünüyorum any.

Yanıtlar:


223

Trueeşittir 1.

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

23
Bu deyimsel değildir ve bool zorlama türünün "kötüye kullanılması" anlamına gelir.
Jan Segre

27
@Jan Segre, zorlama yok, bool bir tamsayı türüdür.
panda-34

28
@ panda-34, kontrol ettim ve issubclass(bool, int)aslında tutuyor, bu yüzden zorlama yok.
Jan Segre

166

listbir countyöntemi vardır:

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

Bu aslında sumamaçtan daha etkilidir ve aynı zamanda amaç hakkında daha açık ve dolayısıyla kullanmak için bir neden yoktur 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
Ayrıca 0 değeri varsa Yanlış değerleri
sayamam

10
sum1 veya Doğru dışında başka "doğru" değerlere sahipseniz, diğer yanıtı kullanamazsınız . Üstelik, soru Trueya da dışında bir şey söylemedi False.
Mark Tolonen

43

Sadece sabitle ilgileniyorsanız True, basit sumbir sorun değildir. Ancak, Python'da diğer değerlerin de değerlendirildiğini unutmayın True. Daha sağlam bir çözüm, boolyerleşik olanı kullanmak olacaktır :

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

GÜNCELLEME: İşte daha şeffaf olma avantajına sahip benzer şekilde güçlü bir çözüm:

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

PS Python trivia: 1 olmadan da doğru True olabilirdi . Uyarı: Bunu işyerinde denemeyin!

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

Çok daha kötü:

True = False

Tamam, örneğini görüyorum ve ne yaptığını görüyorum. LOL olmasının dışında, burada gösterdiklerinizi yapmak için gerçekten iyi bir neden var mı?
acs

1
Evet, üst kısım için. Belirtmiş olduğum gibi, bir "doğru" için Python testi (bir ififadede olduğu gibi ), sadece test etmekten daha karmaşıktır True. Docs.python.org/py3k/library/stdtypes.html#truth adresine bakın . True = 2"Gerçek" kavramı daha karmaşık olduğunu pekiştirmek içindi; biraz fazladan kod kullanarak (yani kullanarak bool()) çözümü daha sağlam ve daha genel hale getirebilirsiniz.
Ned Deily

11
Python 3'te Trueve Falseanahtar kelimelerdir ve bunları değiştiremezsiniz.
ThePiercingPrince

8

Şunları kullanabilirsiniz sum():

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

5

Sadece bütünlük aşkına ( sumgenellikle tercih edilir), filterdoğru değerleri elde etmek için de kullanabileceğimizi belirtmek istedim . Olağan durumda, filterbir işlevi ilk bağımsız değişken olarak kabul eder, ancak onu geçirirseniz None, tüm "doğru" değerleri filtreleyecektir. Bu özellik biraz şaşırtıcıdır, ancak iyi belgelenmiştir ve hem Python 2 hem de 3'te çalışır.

Sürümler arasındaki fark, Python 2'de filterbir liste döndürmesidir, böylece kullanabiliriz len:

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

Ancak Python 3'te filterbir yineleyici döndürür, bu yüzden kullanamayız lenve kullanmaktan kaçınmak istiyorsak sum(herhangi bir nedenle) yineleyiciyi bir listeye dönüştürmeye başvurmamız gerekir (bu da bunu çok daha az güzel yapar):

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

Bu soruya verilen tüm cevapları ve yorumları okuduktan sonra küçük bir deney yapmayı düşündüm.

Ben 50,000 rastgele Boolean oluşturulup denilen sumve countonlara.

İşte sonuçlarım:

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

Emin olmak için birkaç kez daha tekrarladım:

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

Ve gördüğünüz gibi count, 3 kat daha hızlı sum. Bu yüzden yaptığım countgibi kullanmayı öneririm count_it.

Python sürümü: 3.6.7
CPU çekirdeği: 4
RAM boyutu: 16 GB
İşletim Sistemi: Ubuntu 18.04.1 LTS


3

boolÖnce koşmak daha güvenlidir . Bu kolayca yapılır:

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

Ardından, Python'un Doğru veya Yanlış olarak kabul ettiği her şeyi uygun kovaya yakalayacaksınız:

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

Tercih edersen, bir anlama kullanabilirsin:

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

1

len([b for b in boollist if b is True])Oldukça açıklayıcı olduğu için tercih ederim (veya üretici-ifade eşdeğerini). Ignacio Vazquez-Abrams'ın önerdiği cevaptan daha az 'büyülü'.

Alternatif olarak, bool'un int'e dönüştürülebilir olduğunu varsayan, ancak True değeri hakkında hiçbir varsayımda bulunmayan bunu yapabilirsiniz: ntrue = sum(boollist) / int(True)


Çözümünüzün en az iki sorunu var. Birincisi, aynı sağlamlık sorunundan muzdariptir; sadece testi olarak değiştirerek düzeltebileceğiniz if b. Ancak daha da önemlisi, tüm değerlerin aynı anda bellekte olmasını gerektiren ve lenbir üreteç ifadesi ile kullanamayacağınız bir atılabilir liste oluşturuyorsunuz . Çözümün ölçeklenebilmesi için bu tür uygulamalardan kaçınmak daha iyidir.
Ned Deily

@Ned Deily: if bkesinlikle yanlış. Yalnızca soru, gerçek True boolean yerine True olarak değerlendirilen öğelerle ilgiliyse doğru olacaktır. Yine de ikinci noktanı alıyorum. Bu durumda bir varyant var sum(1 if b is True else 0 for b in boollist).
kampu

Başka bir yerde belirttiğim gibi, OP'nin gerçekten sadece 1 değerine sahip bool türündeki nesneleri saymak anlamına mı geldiği, yoksa doğruyu değerlendiren daha büyük ve genel olarak daha kullanışlı olan değerler kümesi mi anlamına geldiği sorusundan bana açık değil. İlki ise, kimlik testi doğru yaklaşımdır ama aynı zamanda sınırlayıcıdır. Bool türündeki nesneler Python'da oldukça garip ördeklerdir, bu dile nispeten yeni bir ekleme. Her halükarda daha basit sum(1 for b in boollist if b is True)
olanı seçerdim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.