it-swarm.com.de

Python Elemente in einer Liste von Objekten mit übereinstimmenden Attributen zählen

Ich versuche einen einfachen und schnellen Weg zu finden, um die Anzahl der Objekte in einer Liste zu zählen, die einem Kriterium entsprechen. z.B.

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

Was ist nun die einfachste Funktion zum Zählen der Anzahl der Objekte in dieser Liste, die auf der Grundlage ihrer Attribute mit einem Argument übereinstimmen? Zum Beispiel 2 für Person.Gender == "F" oder 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

Ich weiß, dass dies eine alte Frage ist, aber heutzutage wäre dies eine Standardmethode

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

Ich fand, dass die Verwendung eines Listenverständnisses und das Abrufen seiner Länge schneller war als die Verwendung von sum().

Nach meine Tests ...

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

... läuft 1,59 mal so schnell wie ...

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

Persönlich denke ich, dass das Definieren einer Funktion in mehrfacher Hinsicht einfacher ist:

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

Insbesondere, wenn Sie eine Abfrage wiederverwenden möchten.

1
kampu

Ich bevorzuge das:

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

Dann kannst du es so benutzen:

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

das ist billig (erstellt keine unnützen Listen usw.) und perfekt lesbar (ich würde sagen besser als sowohl sum(1 for … if …) als auch sum(p.Gender == "F" for …)).

0
Alfe