I have a list of objects with a boolean property.
I'd like to count these objects according to this boolean property - None's included.
Are there functions in the standard library that would be more efficient, terser, or more Pythonic than fully writing out a loop to iterate over them?
Counter
does not seem appropriate, and this nor this solve the problem - as far as I can tell.
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)]
My current solution:
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
CodePudding user response:
You are already covered with Counter
based approaches, here is a simple shortening of what you have:
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)]
And for my take on the best approach:
from collections import Counter
from operator import attrgetter
def _myCounterMethod(lst):
return Counter(map(attrgetter("state"), lst)).most_common()
# already a list of tuples
Convert whatever you have to strings only when you are printing it really and really need to.
CodePudding user response:
I suggest you implement the .count() method
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))
CodePudding user response:
Use 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)
Output
Counter({'True': 1, 'False': 1, 'None': 1})
If strictly list output is needed do:
result = list(counts.items())
print(result)
Output
[('True', 1), ('False', 1), ('None', 1)]
CodePudding user response:
The below seems to work
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)
output
defaultdict(<class 'int'>, {'True': 1, 'False': 1, 'None': 1})