按对象功能创建列表字典

时间:2014-03-17 18:37:26

标签: python arrays

让我说我有一个班级:

class Cat(object):
     color = "White"     # "Black", "Red" or whatever
     name = "..."
     ....

如果我有一个猫的列表,我想用颜色将它们分开并放入列表字典中:

cats = [cat1, cat2, cat3, ...]
cats_by_color = {"White": [cat1, cat3, ...], "Black": [...], ...}

现在我这样做:

cats_by_color ={}
for cat in cats:
    if cat.color not in cats_by_color.keys():    # add new key if needed
        cats_by_color[cat.color] = []
    cats_by_colors[cat.color].append(cat)        # add cat to right list

我有一种强烈的感觉,就是有一种“更加诡异的方式”来做这些事情。怎么做一些单线程?

3 个答案:

答案 0 :(得分:4)

from collections import defaultdict
cats_by_color = defaultdict(list)

for cat in cats:
    cats_by_colors[cat.color].append(cat)

答案 1 :(得分:0)

要在单行中进行,您需要先对列表进行排序,然后使用itertools.groupby()

from operator import attrgetter
from itertools import groupby

color = attrgetter('color')
cats_by_color = {k: list(g) for k, g in groupby(sorted(cats, key=color), color)}

但是,排序比直接循环更昂贵;这不再是单行,但使用collections.defaultdict()至少会使其变得紧凑:

from collections import defaultdict

cats_by_color = defaultdict(list)

for cat in cats:
    cats_by_colors[cat.color].append(cat)

此处defaultdict将为尚未出现在字典中的密钥创建新的list对象,只需尝试访问密钥即可。

答案 2 :(得分:0)

如果你真的想要一行,没有任何进口:

cats_by_colors = {color: [cat for cat in cats if cat.color == color] 
                  for color in set(cat.color for cat in cats)}

但是,因为这会为每个cats迭代所有color(并且一次获得颜色),效率不高!

请注意,您的Cat属性目前是,而非实例属性,应该是:

class Cat:
    def __init__(self, color, name):
        self.color = color
        self.name = name