Python Count Elements in a List of Objects with Matching Attributes

PythonListObjectAttributesCount

Python Problem Overview


I am trying to find a simple and fast way of counting the number of Objects in a list that match a criteria. e.g.

class Person:
    def __init__(self, Name, Age, Gender):
        self.Name = Name
        self.Age = Age
        self.Gender = Gender

# List of People
PeopleList = [Person("Joan", 15, "F"), 
              Person("Henry", 18, "M"), 
              Person("Marg", 21, "F")]

Now what's the simplest function for counting the number of objects in this list that match an argument based on their attributes? E.g., returning 2 for Person.Gender == "F" or Person.Age < 20.

Python Solutions


Solution 1 - Python

class Person:
    def __init__(self, Name, Age, Gender):
        self.Name = Name
        self.Age = Age
        self.Gender = Gender

        
>>> PeopleList = [Person("Joan", 15, "F"), 
              Person("Henry", 18, "M"), 
              Person("Marg", 21, "F")]
>>> sum(p.Gender == "F" for p in PeopleList)
2
>>> sum(p.Age < 20 for p in PeopleList)
2

Solution 2 - Python

I know this is an old question but these days one stdlib way to do this would be

from collections import Counter

c = Counter(getattr(person, 'gender') for person in PeopleList)
# c now is a map of attribute values to counts -- eg: c['F']

Solution 3 - Python

I found that using a list comprehension and getting its length was faster than using sum().

According to my tests...

len([p for p in PeopleList if p.Gender == 'F'])

...runs 1.59 times as fast as...

sum(p.Gender == "F" for p in PeopleList)

Solution 4 - Python

I prefer this:

def count(iterable):
    return sum(1 for _ in iterable)

Then you can use it like this:

femaleCount = count(p for p in PeopleList if p.Gender == "F")

which is cheap (doesn't create useless lists etc) and perfectly readable (I'd say better than both sum(1 for … if …) and sum(p.Gender == "F" for …)).

Solution 5 - Python

Personally I think that defining a function is more simple over multiple uses:

def count(seq, pred):
    return sum(1 for v in seq if pred(v))

print(count(PeopleList, lambda p: p.Gender == "F"))
print(count(PeopleList, lambda p: p.Age < 20))

Particularly if you want to reuse a query.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFacesOfMuView Question on Stackoverflow
Solution 1 - PythonjamylakView Answer on Stackoverflow
Solution 2 - PythonlonetwinView Answer on Stackoverflow
Solution 3 - PythonWebucatorView Answer on Stackoverflow
Solution 4 - PythonAlfeView Answer on Stackoverflow
Solution 5 - PythonkampuView Answer on Stackoverflow