List元素合并到dict

David Wong提问

David Wong [email protected]
发件人当地时间:         发送时间 15:06 (GMT+08:00)。发送地当前时间:下午2:15。 ✆
主题:      [CPyUG] 上来求一个dict合并的优雅一点的方法

有这样一个list

   1 qrs = [{'type': 'a', 'data': 'hello'}, 
   2      {'type': 'b', 'data': 'hello1'}, 
   3      {'type': 'b', 'data': 'hello2'}, 
   4      {'type': 'b', 'data': 'hello3'}, 
   5      {'type': 'a', 'data': 'hello4'}, 
   6      {'type': 'a', 'data': 'hello5'}, 
   7      {'type': 'b', 'data': 'hello6'}, 
   8      {'type': 'b', 'data': 'hello7'}, ]
   9 
  10 #想得到合并后的结果
  11 
  12 result = [{'type': 'a', 'data': ['hello', 'hello4', 'hello5']}, 
  13              {'type': 'b', 'data': ['hello1', 'hello2', 'hello3', 'hello6', 'hello7']}, ]

自己写了一段c样式代码实现了,但觉得很不优雅,很丑陋。 所以问问各位有什么更优雅更Pythonic的方法实现

WooParadog:itertools

WooParadog [email protected]
发件人当地时间:         发送时间 17:09 (GMT+08:00)。发送地当前时间:下午2:14。 ✆

   1 if __name__ == '__main__':
   2     qrs = [{'type': 'a', 'data': 'hello'}, 
   3         {'type': 'b', 'data': 'hello1'}, 
   4         {'type': 'b', 'data': 'hello2'}, 
   5         {'type': 'b', 'data': 'hello3'}, 
   6         {'type': 'a', 'data': 'hello4'}, 
   7         {'type': 'a', 'data': 'hello5'}, 
   8         {'type': 'b', 'data': 'hello6'}, 
   9         {'type': 'b', 'data': 'hello7'}, 
  10         ]
  11 
  12     import itertools
  13     import operator
  14 
  15     li=[]
  16     qrs.sort(key=operator.itemgetter('type'))
  17     for k,g in itertools.groupby(qrs,key=operator.itemgetter('type')):
  18         dic.append({'type':k,'data':[i['data'] for i in g]})
  19     print li

Leo Jay:collections

Leo Jay [email protected]
发件人当地时间:         发送时间 11:30 (GMT+08:00)。发送地当前时间:下午2:12。 ✆

   1 from collections import defaultdict
   2 
   3 d = defaultdict(list)
   4 [d[q['type']].append(q['data']) for q in qrs]
   5 result = [{'type': k, 'data': v} for k, v in d.items()]
   6 print result

sunshine:setdefault()

sunshine [email protected]
发件人当地时间:         发送时间 12:43 (GMT+08:00)。发送地当前时间:下午2:10。 ✆

   1 new_list = {}
   2 
   3 for elem in qrs:
   4     new_list.setdefault(elem['type'], []).append(elem['data'])
   5     
   6 print new_list

效能

         雷钦 [email protected]
发件人当地时间:         发送时间 21:21 (GMT+08:00)。发送地当前时间:下午11:15。 ✆

我测了一下 defaultdict 最快:

groupby     0.11025595665
defaultdict 0.0313220024109
setdefault  0.050852060318

运行环境 python2.6.5 linux

运行代码:

   1 #!/usr/bin/python
   2 
   3 import sys
   4 import random
   5 import time
   6 import itertools
   7 import operator
   8 import collections
   9 
  10 def g(length, typerange):
  11     return [{'type':random.randint(0,typerange),'data':'hello%s' % x } for x in xrange(length)]
  12 
  13 def f1(qrs):
  14    li=[]
  15    qrs.sort(key=operator.itemgetter('type'))
  16    for k,g in itertools.groupby(qrs,key=operator.itemgetter('type')):
  17        li.append({'type':k,'data':[i['data'] for i in g]})
  18    return li
  19 
  20 def f2(qrs):
  21     d = collections.defaultdict(list)
  22     for q in qrs:
  23        d[q['type']].append(q['data'])
  24     result = [{'type': k, 'data': v} for k, v in d.items()]
  25     return result
  26 
  27 def f3(qrs):
  28     new_list = {}
  29     for elem in qrs:
  30         new_list.setdefault(elem['type'], []).append(elem['data'])
  31     result = [{'type': k, 'data': v} for k, v in new_list.items()]
  32     return result
  33 
  34 def t(f, a):
  35     start = time.time()
  36     f(a)
  37     end = time.time()
  38     return end - start
  39 
  40 def main():
  41     l = 100000
  42     tr = 10
  43     try:
  44        l = int(sys.argv[1])
  45     except:
  46        pass
  47 
  48     try:
  49        tr = int(sys.argv[2])
  50     except:
  51        pass
  52 
  53     print 'groupby     %s' % t(f1,g(l,tr))
  54     print 'defaultdict %s' % t(f2,g(l,tr))
  55     print 'setdefault  %s' % t(f3,g(l,tr))
  56 
  57 if __name__ == '__main__':
  58     main()


反馈

创建 by -- ZoomQuiet [2011-11-28 06:17:33]

MiscItems/2011-11-28 (last edited 2011-11-28 15:20:18 by ZoomQuiet)