在元组列表中按字母求和

时间:2016-09-27 21:25:12

标签: python list tuples

我有一个元组列表:

[ ('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ]

我试图总结所有具有相同字母的数字。即我想输出

[('A', 150), ('B', 70), ('C',10)] 

我尝试使用set来获取唯一值但是当我尝试将第一个元素与集合进行比较时我得到了

TypeError: unsupported operand type(s) for +: 'int' and 'str'

任何快速解决方案都可以按字母匹配?

8 个答案:

答案 0 :(得分:1)

为了实现这一点,首先要创建一个字典来存储你的值。然后使用dicttuple list对象转换为.items()。以下是有关如何实现此目标的示例代码:

my_list = [ ('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ]
my_dict = {}
for key, val in my_list:
    if key in my_dict:
        my_dict[key] += val
    else:
        my_dict[key] = val

my_dict.items()
# Output: [('A', 150), ('C', 10), ('B', 70)]

答案 1 :(得分:1)

这个怎么样:(假设a是你提供的元组的名称)

letters_to_numbers = {}
for i in a:
    if i[0] in letters_to_numbers:
        letters_to_numbers[i[0]] += i[1]
    else:
        letters_to_numbers[i[0]] = i[1]
b = letters_to_numbers.items()

生成的元组b的元素将没有特定的顺序。

答案 2 :(得分:1)

这是一个(半个?) - 班轮:逐个字母(你需要先排序),然后取你元组的第二个条目的总和。

from itertools import groupby
from operator import itemgetter

data = [('A', 100), ('B', 50), ('A', 50), ('B', 20), ('C', 10)]
res = [(k, sum(map(itemgetter(1), g)))
       for k, g in groupby(sorted(data, key=itemgetter(0)), key=itemgetter(0))]
print(res)
// => [('A', 150), ('B', 70), ('C', 10)]

以上是O(n log n) - 排序是最昂贵的操作。如果您的输入列表非常大,则可以通过以下O(n)方法获得更好的服务:

from collections import defaultdict

data = [('A', 100), ('B', 50), ('A', 50), ('B', 20), ('C', 10)]

d = defaultdict(int)
for letter, value in data:
    d[letter] += value
res = list(d.items())
print(res)
// => [('B', 70), ('C', 10), ('A', 150)]

答案 3 :(得分:1)

生成元组列表的是什么?是你吗?如果是这样,为什么不尝试使用defaultdict(list)在创建元组列表时将值附加到正确的字母。然后你可以简单地总结它们。见下面的例子。

>>> from collections import defaultdict
>>> val_store = defaultdict(list)
>>> # next lines are me simulating the creation of the tuple
>>> val_store['A'].append(10)
>>> val_store['B'].append(20)
>>> val_store['C'].append(30)
>>> val_store
defaultdict(<class 'list'>, {'C': [30], 'A': [10], 'B': [20]})
>>> val_store['A'].append(10)
>>> val_store['C'].append(30)
>>> val_store['B'].append(20)
>>> val_store
defaultdict(<class 'list'>, {'C': [30, 30], 'A': [10, 10], 'B': [20, 20]})

>>> for val in val_store:
...   print(val, sum(val_store[val]))
... 
C 60
A 20
B 40

答案 4 :(得分:1)

>>> from collections import Counter
>>> c = Counter()
>>> for k, num in items:
        c[k] += num


>>> c.items()
[('A', 150), ('C', 10), ('B', 70)]

效率较低(但效果更好)单线版:

>>> Counter(k for k, num in items for i in range(num)).items()
[('A', 150), ('C', 10), ('B', 70)]

答案 5 :(得分:0)

试试这个:

a = [('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ]

letters = set([s[0] for s in a])

new_a = []
for l in letters:
    nums = [s[1] for s in a if s[0] == l]
    new_a.append((l, sum(nums)))

print new_a    

结果:

[('A', 150), ('C', 10), ('B', 70)]

答案 6 :(得分:0)

更简单的方法

x = [('A',100),('B',50),('A',50),('B',20),('C',10)]
y = {}
for _tuple in x:
    if _tuple[0] in y:
        y[_tuple[0]] += _tuple[1]
    else:
        y[_tuple[0]] = _tuple[1]
print [(k,v) for k,v in y.iteritems()]

答案 7 :(得分:0)

一个班轮:

>>> x = [ ('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ]
>>> {
...     k: reduce(lambda u, v: u + v, [y[1] for y in x if y[0] == k])
...     for k in [y[0] for y in x]
...     }.items()
[('A', 150), ('C', 10), ('B', 70)]