If I have list of tuples like this:
my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'), ('paper', '$15'), ('paper', '$20'), ('paper', '$15')]
how can I turn the list to this:
[('books', '$15'), ('ink', '$20'), ('paper', '$50')]
i.e. to add the expense of same item while both the items are string in the tuples. I have problem with the price items being string. Any hint would be greatly appreciated. Thanks a lot!
I am getting the first list in this way:
my_list=[]
for line in data:
item, price = line.strip('\n').split(',')
cost = ["{:s}".format(item.strip()), "${:.2f}".format(float(price))]
my_list.append(tuple(cost))
Now my_list
should look like given above.
You can use defaultdict
to do this:
>>> from collections import defaultdict
>>> my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'), ('paper', '$15'), ('paper', '$20'), ('paper', '$15')]
>>> res = defaultdict(list)
>>> for item, price in my_list:
... res[item].append(int(price.strip('$')))
...
>>> total = [(k, "${}".format(sum(v))) for k, v in res.items()]
>>> total
[('ink', '$20'), ('books', '$15'), ('paper', '$50')]
This is fairly easy using a dictionary:
result={} #initialize an empty dictionary
for (type,cost) in my_list:
if type not in result.keys():
result[type]=int(cost[1:]) #add entry
else:
result[type]=result[type]+int(cost[1:]) #increment cost
#make dictionary a list again
dictlist=[]
for key, value in result.iteritems():
temp = [key,"$"+str(value)] #add dollar sign
dictlist.append(temp)
print dictlist
Edit: forgot two lines
If your data is already grouped like you sample input, you can use itertools.groupby, grouping by each first element of the tuples and summing the prices in each group:
from itertools import groupby
from operator import itemgetter
my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'), ('paper', '$15'), ('paper', '$20'), ('paper', '$15')]
grouped = [(k, "${}".format(sum(int(s[1][1:]) for s in v)))
for k ,v in groupby(my_list, itemgetter(0))]
Output:
[('books', '$15'), ('ink', '$20'), ('paper', '$50')]
If it were not ordered you could call sorted groupby(sorted(my_list), itemgetter(0))
but changes the complexity to n log n
so a dict option may be better in that case.
You can also do the groupby on data
and forget building an intermediary list, csv.reader
will also split the data for you:
from itertools import groupby
from operator import itemgetter
from csv import reader
grouped = [(k, "${}".format(sum(int(s[1]) for s in v)))
for k, v in groupby(reader(data), itemgetter(0))]
You might be better also leaving the values as ints and formatting when you want to output. Also to handle floats cast to float not int:
from csv import reader
grouped = [(k, sum(float(s[1]) for s in v))
for k, v in groupby(reader(data), itemgetter(0))]
When you want to output you can add the dollar sign and also pad so you get nicely formatted output:
In [10]: "${:.2f}".format(1.0)
Out[10]: '$1.00'
You can simply use a dictionary to solve this problem.
my_list = [('books', '$5'), ('books', '$10'), ('ink', '$20'),
('paper', '$15'), ('paper', '$20'), ('paper', '$15')]
sums = {}
for item, price in my_list:
sums[item] = sums.get(item, 0) + int(price[1:])
print sums
And if you need list of tuples, just do
print sums.items()
And to get your the output you expect,
print [(item, '$' + str(price)) for item, price in sums.items()]
Update
If you have costs with floating point value, you can simply change int
to float
like this and rest of the code remains the same,
sums[item] = sums.get(item, 0) + float(price[1:])
Just for fun, a one-liner:
[(k,'$'+str(sum(int(e[1][1:]) for e in my_list if e[0]==k))) for k in set(map(lambda x:x[0], my_list))]
Don't actually do this.
来源:https://stackoverflow.com/questions/36106823/to-sum-up-values-of-same-items-in-a-list-of-tuples-while-they-are-string