Home > Back-end >  Counting Objects in a List according to a Boolean property
Counting Objects in a List according to a Boolean property

Time:10-12

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})
  • Related