2010-02-12 28 views
15

मैं की एक सूची है (लेबल, गिनती) इस तरह tuples:समूहीकरण अजगर टपल सूची

[('grape', 100), ('grape', 3), ('apple', 15), ('apple', 10), ('apple', 4), ('banana', 3)] 

से है कि मैं एक ही लेबल के साथ सभी मूल्यों (एक ही लेबल हमेशा आसन्न) योग करने के लिए करना चाहते हैं और एक सूची प्रदान एक ही लेबल क्रम में:

[('grape', 103), ('apple', 29), ('banana', 3)] 

मैं जानता हूँ कि मैं की तरह कुछ के साथ इसे हल कर सकते हैं:

def group(l): 
    result = [] 
    if l: 
     this_label = l[0][0] 
     this_count = 0 
     for label, count in l: 
      if label != this_label: 
       result.append((this_label, this_count)) 
       this_label = label 
       this_count = 0 
      this_count += count 
     result.append((this_label, this_count)) 
    return result 

लेकिन वहाँ एक मो है ऐसा करने के लिए पाइथोनिक/सुरुचिपूर्ण/कुशल तरीका?

उत्तर

23

itertools.groupby आप क्या चाहते हैं कर सकते हैं:

import itertools 
import operator 

L = [('grape', 100), ('grape', 3), ('apple', 15), ('apple', 10), 
    ('apple', 4), ('banana', 3)] 

def accumulate(l): 
    it = itertools.groupby(l, operator.itemgetter(0)) 
    for key, subiter in it: 
     yield key, sum(item[1] for item in subiter) 

>>> print list(accumulate(L)) 
[('grape', 103), ('apple', 29), ('banana', 3)] 
>>> 
+4

मुझे 'लैम्ब्डा' के स्थान पर 'operator.itemgetter' के उपयोग को पसंद है। – jathanism

+1

इस सूची को पहली कुंजी पर सॉर्ट करने की आवश्यकता है। यदि यह पहले से सॉर्ट नहीं किया गया है, तो ghostdog74 से डिफ़ॉल्ट डिक्शन दृष्टिकोण एक बेहतर समाधान है। –

5

itertools और सूची का उपयोग कर comprehensions

import itertools 

[(key, sum(num for _, num in value)) 
    for key, value in itertools.groupby(l, lambda x: x[0])] 

संपादित करें: gnibbler के रूप में ने कहा: अगर l है पहले से ही sorted(l) से बदलने का हल नहीं।

+4

बिना मेरे संस्करण का उपयोग करने GroupBy आप पहली बार यह सुनिश्चित करना चाहिए कि अनुक्रम pregrouped है (सभी 'अंगूर' आसन्न, आदि)। ऐसा करने का एक तरीका अनुक्रम को क्रमबद्ध करना है –

+0

ओपी ने कहा कि लेबल पहले से ही समूहीकृत किए गए थे। –

+0

@ थॉमस वौटर, हाँ आप सही हैं ("एक ही लेबल हमेशा निकट होते हैं") –

3
import collections 
d=collections.defaultdict(int) 
a=[] 
alist=[('grape', 100), ('banana', 3), ('apple', 10), ('apple', 4), ('grape', 3), ('apple', 15)] 
for fruit,number in alist: 
    if not fruit in a: a.append(fruit) 
    d[fruit]+=number 
for f in a: 
    print (f,d[f]) 

उत्पादन

$ ./python.py 
('grape', 103) 
('banana', 3) 
('apple', 29) 
3
>>> from itertools import groupby 
>>> from operator import itemgetter 
>>> L=[('grape', 100), ('grape', 3), ('apple', 15), ('apple', 10), ('apple', 4), ('banana', 3)] 
>>> [(x,sum(map(itemgetter(1),y))) for x,y in groupby(L, itemgetter(0))] 
[('grape', 103), ('apple', 29), ('banana', 3)] 
0

या एक सरल अधिक पठनीय जवाब (itertools के बिना):

pairs = [('foo',1),('bar',2),('foo',2),('bar',3)] 

def sum_pairs(pairs): 
    sums = {} 
    for pair in pairs: 
    sums.setdefault(pair[0], 0) 
    sums[pair[0]] += pair[1] 
    return sums.items() 

print sum_pairs(pairs) 
1

itertools
[(k, sum([y for (x,y) in l if x == k])) for k in dict(l).keys()]

संबंधित मुद्दे