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

后端 未结 5 686
一整个雨季
一整个雨季 2021-01-23 01:56

If I have list of tuples like this:

my_list = [(\'books\', \'$5\'), (\'books\', \'$10\'), (\'ink\', \'$20\'), (\'paper\', \'$15\'), (\'paper\', \'$20\'), (\'pap         


        
相关标签:
5条回答
  • 2021-01-23 02:37

    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'
    
    0 讨论(0)
  • 2021-01-23 02:37

    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

    0 讨论(0)
  • 2021-01-23 02:38

    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')]
    
    0 讨论(0)
  • 2021-01-23 02:43

    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:])
    
    0 讨论(0)
  • 2021-01-23 02:58

    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.

    0 讨论(0)
提交回复
热议问题