python: sum values in a list if they share the first word

Viewed 161

I have a list as follows,

flat_list = ['hello,5', 'mellow,4', 'mellow,2', 'yellow,2', 'yellow,7', 'hello,7', 'mellow,7', 'hello,7']

I would like to get the sum of the values if they share the same word, so the output should be,

desired output:

l = [('hello',19), ('yellow', 9), ('mellow',13)]

so far, I have tried the following,

new_list = [v.split(',') for v in flat_list]

d = {}
for key, value in new_list:
   if key not in d.keys():
      d[key] = [key]
   d[key].append(value)

# getting rid of the first key in value lists
val = [val.pop(0) for k,val in d.items()]
# summing up the values
va = [sum([int(x) for x in va]) for ka,va in d.items()]

however for some reason the last sum up does not work and i do not get my desired output

6 Answers

Here is a variant for accomplishing your goal using defaultdict:

from collections import defaultdict

t = ['hello,5', 'mellow,4', 'mellow,2', 'yellow,2',
     'yellow,7', 'hello,7', 'mellow,7', 'hello,7']

count = defaultdict(int)

for name_number in t:
    name, number = name_number.split(",")
    count[name] += int(number)

You could also use Counter:

from collections import Counter

count = Counter()

for name_number in t:
    name, number = name_number.split(",")
    count[name] += int(number)

In both cases you can convert the output to a list of tuples using:

list(count.items())
# -> [('hello', 19), ('mellow', 13), ('yellow', 9)]

I ran your code and I do get the correct results (although not in your desired format).

One possible approach would be:

import pandas as pd
    
flat_list = ['hello,5', 'mellow,4', 'mellow,2', 'yellow,2', 'yellow,7', 'hello,7', 'mellow,7', 'hello,7']
new_list = [v.split(',') for v in flat_list]
    
df = pd.DataFrame(new_list)
df[1] = df[1].astype(int)
df2 = df.groupby(0).sum()
print(df2)

Output:

    0        1
    hello   19
    mellow  13
    yellow   9

You can do this very simply without importing additional modules like so:

t = ['hello,5', 'mellow,4', 'mellow,2', 'yellow,2', 'yellow,7', 'hello,7', 'mellow,7', 'hello,7']

d = {}
for s in t: #for each string
    w, n = s.split(',') #get the string and the number
    d[w] = d[w] + int(n) if w in d.keys() else int(n) #add the number (sum)

l = list(d.items()) #make the result a list of tuples
print(l)

Output:

[('hello', 19), ('mellow', 13), ('yellow', 9)]

the last sum up does not work and i do not get my desired output

Actually it works fine, you just forgot to combine the two lists. Add

print(list(zip(val, va)))

and you'll see:

[('hello', 19), ('mellow', 13), ('yellow', 9)]

That's equivalent to your desired output:

[('hello',19), ('yellow', 9), ('mellow',13)]

Only the entries for yellow and mellow are in different order, since mellow appears first in the input.

Summarising the replies above I'd say that the cleanest way, without the need of external imports, seems to be:

flat_list = ['hello,5', 'mellow,4', 'mellow,2', 'yellow,2', 
             'yellow,7', 'hello,7', 'mellow,7', 'hello,7']

d = {}
for ele in flat_list:
    key, value = ele.split(',')
    d[key]= d.get(key, 0) + int(value)
    
list(d.items())

And the output is:

[('hello', 19), ('mellow', 13), ('yellow', 9)]

That can be sorted by increasing value like this (or alphabetically using x[0]; set reverse to True for descending order):

sorted(list(d.items()), key=lambda x: x[1], reverse=False)

for some reason the last sum up does not work

To fix your original solution:

d = {ka:sum([int(x) for x in va]) for ka,va in d.items()}
Related