代码之家  ›  专栏  ›  技术社区  ›  hoju

分组python元组列表

  •  19
  • hoju  · 技术社区  · 15 年前

    我有一个(label,count)元组列表,如下所示:

    [('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
    

    但是,有没有一种更像蟒蛇/优雅/高效的方法来做到这一点?

    7 回复  |  直到 6 年前
        1
  •  30
  •   Thomas Wouters    15 年前

    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)]
    >>> 
    
        2
  •  6
  •   cobbal    15 年前

    使用ITertools和列表理解

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

    编辑: 正如Gnibbler指出的那样:如果 l 尚未排序,请将其替换为 sorted(l) .

        3
  •  5
  •   ghostdog74    15 年前
    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)
    
        4
  •  4
  •   John La Rooy    15 年前
    >>> 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)]
    
        5
  •  2
  •   Anton Suslov    7 年前

    我的版本没有itertools
    [(k, sum([y for (x,y) in l if x == k])) for k in dict(l).keys()]

        6
  •  0
  •   Paul Kenjora    8 年前

    或者更简单易读的答案(不带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)
    
        7
  •  0
  •   Shameem    6 年前

    方法

    def group_by(my_list):
        result = {}
        for k, v in my_list:
            result[k] = v if k not in result else result[k] + v
        return result 
    

    用法

    my_list = [
        ('grape', 100), ('grape', 3), ('apple', 15),
        ('apple', 10), ('apple', 4), ('banana', 3)
    ]
    
    group_by(my_list) 
    
    # Output: {'grape': 103, 'apple': 29, 'banana': 3}
    

    转换成元组列表 list(group_by(my_list).items()) .