问题
I have a list of tuples:
[ ('A',100), ('B',50), ('A',50), ('B',20), ('C',10) ]
I am trying to sum up all numbers that have the same letter. I.e. I want to output
[('A', 150), ('B', 70), ('C',10)]
I have tried using set to get the unique values but then when I try and compare the first elements to the set I get
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Any quick solutions to match the numbers by letter?
回答1:
Here is a one(and a half?)-liner: group by letter (for which you need to sort before), then take the sum of the second entries of your tuples.
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)]
The above is O(n log n) — sorting is the most expensive operation. If your input list is truly large, you might be better served by the following O(n) approach:
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)]
回答2:
How about this: (assuming a
is the name of the tuple you have provided)
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()
The elements of the resulting tuple b
will be in no particular order.
回答3:
In order to achieve this, firstly create a dictionary to store your values. Then convert the dict
object to tuple list
using .items()
Below is the sample code on how to achieve this:
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)]
回答4:
What is generating the list of tuples? Is it you? If so, why not try a defaultdict(list) to append the values to the right letter at the time of making the list of tuples. Then you can simply sum them. See example below.
>>> 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
回答5:
>>> from collections import Counter
>>> c = Counter()
>>> for k, num in items:
c[k] += num
>>> c.items()
[('A', 150), ('C', 10), ('B', 70)]
Less efficient (but nicer looking) one liner version:
>>> Counter(k for k, num in items for i in range(num)).items()
[('A', 150), ('C', 10), ('B', 70)]
回答6:
Try this:
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
Results:
[('A', 150), ('C', 10), ('B', 70)]
回答7:
A simpler approach
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()]
回答8:
A one liner:
>>> 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)]
来源:https://stackoverflow.com/questions/39734549/sum-numbers-by-letter-in-list-of-tuples