У меня есть список объектов с логическим свойством.

Я хотел бы подсчитать эти объекты в соответствии с этим логическим свойством - Ничего не включено.

Есть ли в стандартной библиотеке функции, которые были бы более эффективными, лаконичными или более питоническими, чем полное написание цикла для их итерации?

Counter не кажется подходящим, и это, ни это решить проблему - насколько я могу судить.

class MyObject():
    def __init__(self, moniker, booleanVariable):
        self.name = moniker
        self.state = booleanVariable

def _myCounterMethod(list):
    # code goes here
    return counts

myList = []
myList.append(MyObject("objectOne", True))
myList.append(MyObject("objectTwo", False))
myList.append(MyObject("objectThree", None))

counts = _MyCounterMethod(myList)
print(counts)
>>>[('True', 1), ('False', 1), ('None', 1)]

Мое текущее решение:

def _myCounterMethod(list):
    trueCount = 0
    falseCount = 0
    noneCount = 0
    for obj in list:
        if obj.state == True:
            trueCount += 1
        elif obj.state == False:
            falseCount += 1
        elif obj.state == None:
            noneCount += 1
    countsList = [('True', trueCount), ('False', falseCount), ('None', noneCount)]
    return countsList
1
farAndAway 11 Окт 2021 в 19:00

4 ответа

Лучший ответ

Используйте collections.Counter:

import collections


class MyObject():
    def __init__(self, moniker, booleanVariable):
        self.name = moniker
        self.state = booleanVariable


my_list = [MyObject("objectOne", True), MyObject("objectTwo", False), MyObject("objectThree", None)]

counts = collections.Counter(str(e.state) for e in my_list)
print(counts)

Вывод

Counter({'True': 1, 'False': 1, 'None': 1})

Если требуется вывод строго списка, выполните:

result = list(counts.items())
print(result)

Вывод

[('True', 1), ('False', 1), ('None', 1)]
1
Dani Mesejo 11 Окт 2021 в 16:12

Вы уже знакомы с подходами, основанными на Counter, вот простое сокращение того, что у вас есть:

def _myCounterMethod(lst):  # do not shadow `list`
    trueCount = falseCount = noneCount = 0
    for obj in lst:
        trueCount += obj.state is True
        falseCount += obj.state is False
        noneCount += obj.state is None
    return [('True', trueCount), ('False', falseCount), ('None', noneCount)]

И на мой взгляд, лучший подход:

from collections import Counter
from operator import attrgetter

def _myCounterMethod(lst):
    return Counter(map(attrgetter("state"), lst)).most_common()
    # already a list of tuples

Преобразуйте все, что у вас есть, в строки только тогда, когда вы печатаете это действительно и действительно необходимо.

2
schwobaseggl 11 Окт 2021 в 16:33

Предлагаю вам реализовать метод .count ()

def counter(l):
   iter = [x.state for x in l]
   return ('True', iter.count(True)), ('False', iter.count(False)), ('None', iter.count(None))
>>> counter(myList)
(('True', 1), ('False', 1), ('None', 1))
1
Alexandre Mahdhaoui 11 Окт 2021 в 16:06

Кажется, что ниже работает

from collections import defaultdict

data = defaultdict(int)
class MyObject():
    def __init__(self, moniker, booleanVariable):
        self.name = moniker
        self.state = booleanVariable
myList = []
myList.append(MyObject("objectOne", True))
myList.append(MyObject("objectTwo", False))
myList.append(MyObject("objectThree", None))
for o in myList:
  data[str(o.state)] += 1
print(data)

Выход

defaultdict(<class 'int'>, {'True': 1, 'False': 1, 'None': 1})
0
balderman 11 Окт 2021 в 16:05