2013-05-09 2 views
22

Я пытаюсь найти простой и быстрый способ подсчета количества объектов в списке, который соответствует критериям. , например.Элементы Python Count в списке объектов с соответствующими атрибутами

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

Теперь то, что это самая простая функция для подсчета количества объектов в этом списке, которые соответствуют аргументу на основе их атрибутов? Например, возвращаясь 2 для Person.Gender == "F" или person.age < 20.

ответ

28
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 
+15

Я предпочитаю 'sum (1 для p в PeopleList, если p.Gender ==" F ")', потому что он не злоупотребляет тем, что bool подкласс int. – wim

+4

@wim http://stackoverflow.com/questions/3174392/is-it-pythonic-to-use-bools-as-ints –

+0

Да, я знаю об этом сообщении и уже имею свой 1 голос на ответ Алекса , ;) См. Также http://stackoverflow.com/a/8169049/674039 – wim

1

Лично я считаю, что определение функции является более простым в течение нескольких использований:

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

Особенно если вы хотите повторно использовать запрос.

+0

Edit: Понятно, я поменял позицию «if». спасибо, исправлено. – kampu

0

Я предпочитаю это:

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

Затем вы можете использовать его как это:

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

который является дешевым (не создавать ненужные списки и т.д.) и отлично читается (я бы сказал, лучше, чем у sum(1 for … if …) и sum(p.Gender == "F" for …)).

4

Я обнаружил, что использование списка и получение его длины было быстрее, чем использование sum().

Согласно my tests ...

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

... работает 1,59 раза быстрее, чем ...

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

Не справедливый тест, если вы также не проверите 'sum ([p.Gender ==" F "для p в PeopleList])' и опубликуйте результаты для крошечных, средних и гигантских данных – jamylak

6

Я знаю, что это старый вопрос, но в эти дни один STDLIB способ сделайте это будет

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'] 
Смежные вопросы