Python使用匹配的属性获取列表中的对象

时间:2013-12-13 00:58:09

标签: python list attributes generator

我有一个对象列表,需要获取一个属性具有相同值的所有对象才能进一步处理它们。我用谷歌搜索过的所有东西都已经知道了我正在寻找的价值。相反,我只需要比赛。说我有这个

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = Person("mike", 28)
p2 = Person("joe", 28)
p3 = Person("nick", 27)
p4 = Person("Janet", 27)
people = [p1, p2, p3]
#need something like
matches = getMatches(people, "age")
print matches
[[Mike's object, Joe' Object], [Nick's object, Janet's object]]

我提出了这个并且它有效,但对我来说似乎有点糟糕

def getMatches(objs, attr):
    def Gen(objs, attr):
        used = [] #already searched for these...
        for obj in objs:
            a = getattr(obj, attr)
            if a not in used:
                yield [p for p in objs if getattr(p, attr) == a]
            used.append(a)
    gen = Gen(objs, attr)
    return [g for g in gen]

在我的实际代码中,需要它更有意义。任何人都可以帮我清理这个或者是否有一个标准的功能或方法来实现这一点,我只是不知道?

我很感激答案,最后使用groupby并确保先对它们进行排序。这是我第一次尝试编写生成器。如果我可以问,是什么让我的代码正确和pythonic,可以这么说?

2 个答案:

答案 0 :(得分:3)

您可以像这样使用operator.attrgetteritertools.groupby

from operator import attrgetter
from itertools import groupby
def getMatches(people, prop):
    people = sorted(people, key = attrgetter(prop))
    return [list(grp) for k, grp in groupby(people, attrgetter(prop))]

print getMatches(people, "age")

您可以像这样检查结果

for group in getMatches(people, "age"):
    print [people.name for people in group]

<强>输出

['mike', 'joe']
['nick', 'Janet']

答案 1 :(得分:0)

怎么样:

def get_matches(objs, key):
    d = {}
    for obj in objs:
        d.setdefault(getattr(obj, key), []).append(obj)
    return d

之后[我添加了repr]:

>>> get_matches(people, "age")
{27: [{'name': 'nick', 'age': 27}, {'name': 'Janet', 'age': 27}], 
 28: [{'name': 'mike', 'age': 28}, {'name': 'joe', 'age': 28}]}

这提供的一个优点是groupby通过连续的值进行分组。如果这就是你想要的,那就完美了。否则,您必须记住首先按键功能排序。 (这里的缺点是它不会保留键值的出现顺序,但如果我们真的关心的话,我们可以使用collections.OrderedDict。)