python 可分组字典

本文介绍如何使用Python对对象集合按属性进行高效分组,包括直接字典操作、使用defaultdict及reduce方法等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


class Person(object):
def __init__(self,first_name,last_name):
self.first_name =first_name
self.last_name = last_name

def __repr__(self):
return u"first name :" + unicode(self.first_name) \
+ u" ; last name :" + unicode(self.last_name)


a1 = [Person(u"liu", u"xing"), Person(u"liu", u"xu"), Person(u"zhang", u"xing")]
a2 = [Person(u"liu", u"qin"), Person(u"li", u"jun"), Person(u"zhang", u"hua")]



使用python 开发时,是不是时常有这样的需求,对一个集合的每个对象,按照某属性分类,比如
需要按照姓来分组,同姓的分在一个组内。大伙比较常见的做法如下:


d = {}
for per in a1:
if per.first_name not in d:
d[per.first_name] = []
d[per.first_name].append(per)
for per in a2:
if per.first_name not in d:
d[per.first_name] = []
d[per.first_name].append(per

python中对dict的默认值有设置,详见python doc的[url=http://docs.python.org/library/stdtypes.html?highlight=setdefault#dict.setdefault]dict.setdefault[/url]


d = {}
for per in a1:
d.setdefault(per.first_name, []).append(per)
for per in a2:
d.setdefault(per.first_name, []).append(per)


python提供自动创建默认值的结构[url="http://docs.python.org/library/collections.html?highlight=defaultdict#collections.defaultdict"]defaultdict[/url]

进一步优化,如下:

d = defaultdict(list)
for per in a1:
d[per.first_name].append(per)
for per in a2:
d[per.first_name].append(per)

熟悉列表推导或者[url="http://docs.python.org/library/functions.html?highlight=map#map"]map[/url]方法的进一步优化:

d = defaultdict(list)
map(lambda per:d[per.first_name].append(per),a1)
map(lambda per:d[per.first_name].append(per),a2)

d = defaultdict(list)
[d[per.first_name].append(per) for per in a1]
[d[per.first_name].append(per) for per in a2]


还有进一步优化的可能吗?熟悉[url="http://docs.python.org/library/functions.html?highlight=map#reduce"]reduce[/url]的朋友可以看下我提供的解决方案,代码如下:
[code]
class GroupDict(defaultdict):

def __init__(self, default_factory=list):
'''
@param default_factory: default value generator
'''
super(GroupDict, self).__init__(default_factory)
default_value_type = default_factory if default_factory else list
if issubclass(default_value_type, list) :
self._add_function = default_value_type.append
elif issubclass(default_value_type, set):
self._add_function = default_value_type.add

def append_2_value_collection(self, k, value):
'''
@param k: the key
@param value: the value to add to self[k]
@return: self
@attention: it's important to return self
'''
self._add_function(self[k], value)
return self
[/code]
那有了这个类,和reduce配合起来就可以像使用jQuery一样链式编写代码了

d = reduce(lambda d, per:d.append_2_value_collection(per.first_name, per), a1, GroupDict())
reduce(lambda d, per:d.append_2_value_collection(per.first_name, per), a2 , d)

for k,v in d.iteritems():
print k ,u"...."
for per in v:
print per

输出结果和上述前几个完全一致。该结构完全继承了dict的功能,只有一个需要注意的,就是一旦使用继承下的方法修改value为非default_factory实例后,再次调用append_2_value_collection将抛异常。请朋友们进一步完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值