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的dict.setdefault
d = {}
for per in a1:
d.setdefault(per.first_name, []).append(per)
for per in a2:
d.setdefault(per.first_name, []).append(per)
python提供自动创建默认值的结构defaultdict
进一步优化,如下:
d = defaultdict(list)
for per in a1:
d[per.first_name].append(per)
for per in a2:
d[per.first_name].append(per)
熟悉列表推导或者map方法的进一步优化:
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]
还有进一步优化的可能吗?熟悉reduce的朋友可以看下我提供的解决方案,代码如下:
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
那有了这个类,和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将抛异常。请朋友们进一步完善。
0
顶
2
踩
分享到:
2012-07-01 00:44
浏览 6540
评论