To sum up values of same items in a list of tuples while they are string

旧巷老猫 提交于 2019-12-01 23:23:26

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!