我有一个此类的对象列表:
class foo:
def __init__(self,x,y):
self.x = x
self.y = y
def __repr__(self):
return "(" + str(self.x) + "," + str(self.y) + ")"
现在,我想创建一个字典,其中包含x
的每个值的列表(排序的,唯一的元素),其中包含y
的值。我写了这个
def get_xy_dict(lis):
outp = {}
for e in lis:
if (e.x in outp):
outp[e.x].add(e.y)
else:
outp[e.x] = set([e.y])
return outp
像这样使用它,可以按预期工作:
x = [ foo(1,2), foo(1,3), foo(3,6), foo(1,3)]
y = get_xy_dict(x)
print(x)
print(y)
打印(请参见here):
[(1,2), (1,3), (3,6), (1,3)]
{1: {2, 3}, 3: {6}}
但是,我觉得我的代码非常笨拙。而且,我更喜欢列表而不是集合。也许可以完全避免使用这些集。也是出于巧合,对输出进行了排序,如果再加上它,它将变得更加笨拙。
获得相同输出(最好是列表而不是集合)的pythonic方法是什么?即,如何生成包含给定y
出现的所有x
值的字典?
PS:不确定,如果这属于codereview,请告诉我。
答案 0 :(得分:2)
您首先需要按 x 属性对foo项目进行排序,然后才能对它们进行分组。
一种方法是使用itertools.groupby
,如下所示:
import itertools
import operator
sort_key = operator.attrgetter('x')
y = {k: set(v.y for v in group)
for k, group in itertools.groupby(sorted(x, key=sort_key), sort_key)}
print(y)
您得到:
{1: {2, 3}, 3: {6}}
答案 1 :(得分:1)
您可以使用sorted
功能轻松地将集合更改为排序列表。与defaultdict
结合使用,您可以大大简化代码:
from collections import defaultdict
def get_xy_dict(lis):
d = defaultdict(set)
for e in lis:
d[e.x].add(e.y)
return {k: sorted(v) for k, v in d.items()} # This creates a new dict, but you could also
# change the values of d
x = [ foo(1,2), foo(1,3), foo(3,6), foo(1,3)]
y = get_xy_dict(x)
print(x) # [(1,2), (1,3), (3,6), (1,3)]
print(y) # {1: [2, 3], 3: [6]}