Python 按对象特征创建列表字典
假设我有一门课:Python 按对象特征创建列表字典,python,arrays,Python,Arrays,假设我有一门课: class Cat(object): color = "White" # "Black", "Red" or whatever name = "..." .... 如果我有一个猫的列表,我想按颜色将它们分开,并放入列表字典: cats = [cat1, cat2, cat3, ...] cats_by_color = {"White": [cat1, cat3, ...], "Black": [...], ...} 现在我这样做: ca
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
我有一种强烈的感觉,做这样的事情有一种“更像pythonish的方式”。如何做到这一点的一些班轮 要在一行中完成,您需要先对列表进行排序,然后使用:
from collections import defaultdict
cats_by_color = defaultdict(list)
for cat in cats:
cats_by_colors[cat.color].append(cat)
然而,排序比直接循环的成本更高;这不再是一个单衬里,但使用至少使其紧凑:
from collections import defaultdict
cats_by_color = defaultdict(list)
for cat in cats:
cats_by_colors[cat.color].append(cat)
这里,
defaultdict
将为字典中尚未包含的键创建一个新的list
对象,只需尝试访问该键。要在一行中完成此操作,您需要先对列表排序,然后使用:
然而,排序比直接循环的成本更高;这不再是一个单衬里,但使用至少使其紧凑:
from collections import defaultdict
cats_by_color = defaultdict(list)
for cat in cats:
cats_by_colors[cat.color].append(cat)
在这里,
defaultdict
将为尚未在字典中的键创建一个新的列表
对象,只需尝试访问该键。如果您确实希望它在一行中,而不需要任何导入:
cats_by_colors = {color: [cat for cat in cats if cat.color == color]
for color in set(cat.color for cat in cats)}
但是,由于这会对所有的猫
进行迭代,因此对于每种颜色
(以及一次获取颜色),这不是很有效
请注意,您的Cat
属性当前是类,而不是实例属性,应该是:
class Cat:
def __init__(self, color, name):
self.color = color
self.name = name
如果您确实希望它在一行中,而不需要任何导入:
cats_by_colors = {color: [cat for cat in cats if cat.color == color]
for color in set(cat.color for cat in cats)}
但是,由于这会对所有的猫
进行迭代,因此对于每种颜色
(以及一次获取颜色),这不是很有效
请注意,您的Cat
属性当前是类,而不是实例属性,应该是:
class Cat:
def __init__(self, color, name):
self.color = color
self.name = name
此
如果cat.color不在cats\u by\u color.keys():#如果需要添加新的键cats\u by\u color[cat.color]=[]
可以替换为默认的dict
,首先,它们也是itertools.groupby
,但它需要一个排序列表。如果cat.color不在cats\u by\u color.keys():#根据需要添加新键cats by_color[cat.color]=[]可以替换为默认dict
,首先,它们也是itertools.groupby
,但需要排序列表。神圣指数列表迭代!你知道你现在是N平方次循环了,对吗?除非每只猫都有不同的颜色。。。我会注意到,虽然这是整洁的,但它不是有效的!set()
production是一个完整的N
迭代,然后N次迭代的子集将再次执行N
的完整循环。不完全是N平方,但远没有效率。@MartijnPieters我希望,即使猫的数量变得非常大,离散颜色的数量也会保持很小(~O(1)
),因此我会得到O(N)
的整体性能。我建议绝育以保持n
小!你最多只能得到O(KN),其中K是唯一的猫的颜色数。groupby解决方案是O(NlogN),我敢打赌在大多数情况下logN将小于K。确定独特颜色的数量将花费更多(构建集合)。神圣指数列表迭代!你知道你现在是N平方次循环了,对吗?除非每只猫都有不同的颜色。。。我会注意到,虽然这是整洁的,但它不是有效的!set()
production是一个完整的N
迭代,然后N次迭代的子集将再次执行N
的完整循环。不完全是N平方,但远没有效率。@MartijnPieters我希望,即使猫的数量变得非常大,离散颜色的数量也会保持很小(~O(1)
),因此我会得到O(N)
的整体性能。我建议绝育以保持n
小!你最多只能得到O(KN),其中K是唯一的猫的颜色数。groupby解决方案是O(NlogN),我敢打赌在大多数情况下logN将小于K。确定独特颜色的数量将花费更多(制作布景)。@mgilson:不过你错过了帖子中的另一个错误:-P(在groupby()
调用中没有右括号)。如何(lambda d={}:[d.setdefault(c.color,[])。在cats中为c添加(c)和d)(
对于no-import 1 liner.Ick,副作用的列表理解!我的神圣符号和花环在哪里!我试图找出如何把它变成一个真正的一行-这是我唯一能想到的方法。但无论如何,我真正的目的是使用defaultdict。。。不需要为了满足一些愚蠢的“1-liner”需求而引入O(nlogn)算法。在这一点上,我反反复复,但当我真实地面对自己时,我认为回答“给我一行”的问题对语言来说并不是最好的——它让人觉得一行比多行要好,而不是追求好的、惯用的python。@mgilson:我同意;我在回答中解释了为什么这不是一个好主意。@mgilson:不过你错过了帖子中的另一个打字错误-P(在groupby()
调用中没有右括号)。如何(lambda d={}:[d.setdefault(c.color,[])。在cats中为c添加(c)和d)(
对于no-import 1 liner.Ick,副作用的列表理解!我的神圣符号和花环在哪里!我试图找出如何把它变成一个真正的一行-这是我唯一能想到的方法。但无论如何,我真正的目的是使用defaultdict。。。不需要为了满足一些愚蠢的“1-liner”需求而引入O(nlogn)算法。在这一点上,我反反复复,但当我真实地面对自己时,我认为回答“给我一行”的问题对语言来说并不是最好的——它让人觉得一行比多行要好,而不是追求好的、惯用的python。@mgilson:我同意;我在ans中解释了为什么这不是一个好主意