web-dev-qa-db-ja.com

グループ化Pythonタプルリスト

私はこのような(ラベル、カウント)タプルのリストを持っています:

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

しかし、これを行うためのよりPythonic /エレガント/効率的な方法はありますか?

22
hoju

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)]
>>> 
35
Thomas Wouters

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)に置き換えます。

6
cobbal
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)
5
ghostdog74
>>> 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)]
4
John La Rooy

itertoolsなしの私のバージョン
[(k, sum([y for (x,y) in l if x == k])) for k in dict(l).keys()]

2
Anton Suslov

方法

_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())のようなタプルのリストに変換します。

1
Shameem

または、より単純で読みやすい回答(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)
0
Paul Kenjora