Sum numbers by letter in list of tuples

前端 未结 8 1581
不思量自难忘°
不思量自难忘° 2020-12-11 09:44

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 s

相关标签:
8条回答
  • 2020-12-11 09:58

    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.

    0 讨论(0)
  • 2020-12-11 10:01

    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
    
    0 讨论(0)
  • 2020-12-11 10:02

    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)]
    
    0 讨论(0)
  • 2020-12-11 10:06

    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()]
    
    0 讨论(0)
  • 2020-12-11 10:10

    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)]
    
    0 讨论(0)
  • 2020-12-11 10:11

    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)]
    
    0 讨论(0)
提交回复
热议问题