web-dev-qa-db-fra.com

Python Compter les éléments dans une liste d'objets avec des attributs correspondants

J'essaie de trouver un moyen simple et rapide de compter le nombre d'objets dans une liste qui correspondent à un critère. par exemple.

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

Maintenant, quelle est la fonction la plus simple pour compter le nombre d'objets dans cette liste qui correspondent à un argument basé sur leurs attributs? Par exemple, renvoyer 2 pour Person.Gender == "F" ou Person.Age <20.

34
FacesOfMu
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
44
jamylak

Je sais que c'est une vieille question mais ces jours-ci, une façon standard de le faire serait

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']
11
lonetwin

J'ai trouvé que l'utilisation d'une compréhension de liste et l'obtention de sa longueur étaient plus rapides que l'utilisation de sum().

Selon mes tests ...

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

... tourne 1,59 fois plus vite que ...

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

Personnellement, je pense que la définition d'une fonction est plus simple sur plusieurs utilisations:

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

Surtout si vous souhaitez réutiliser une requête.

1
kampu

Je préfère ça:

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

Ensuite, vous pouvez l'utiliser comme ceci:

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

qui est bon marché (ne crée pas de listes inutiles, etc.) et parfaitement lisible (je dirais mieux que les deux sum(1 for … if …) et sum(p.Gender == "F" for …)).

0
Alfe