简体   繁体   中英

Given a list of [string, number] tuples, create a dictionary where keys are the first characters of strings and the values are sums of the numbers

I have a list of tuples, where first object is a string and second one is a number. I need to create a dictionary with using first letter of the string as a key and number (or I need to add some numbers if keys will be the same) as a value. for example:

input

lst = [('Alex', 5), ('Addy', 7), ('Abdul', 2), ('Bob', 6), ('Carl', 8), ('Cal', 4)]

output

dct = {'A': 14, 'B': 6, 'C': 12}

The most simple, straightforward and naive way is:

dct = {}
for k, v lst:
    if k in v:
        dct[k] += v
    else:
        dct[k] = v

There are ways to progressively be more clever, the first is probably to use .get with the default:

dct = {}
for k, v in lst:
    dct[k] = dct.get(k, 0) + v

Finally, you can use a collections.defaultdict , which takes a "factory" function which will be called if the key is not there, use int as the factor:

from collections import defaultdict
dct = defaultdict(int)
for k, v in lst:
    dct[k] += v

NOTE: it is usually safer to create a regular dict out of this, to avoid the default behavior:

dct = dict(dct)

Or even

dct.default_factory = None

Finally, one of the more flexible ways is to create your own dict subclass and use __missing__ , this is useful if need access to the key when you are making the default value, so not particularly more helpful here, but for completion's sake:

class AggDict(dict):
    def __missing__(self, key):
        return 0

dct = AggDict()
for k, v in dct:
    dct[k] += v

Use a defaultdict :

dct = defaultdict(int) # default to 0

for name, val in lst:
    dct[name[0]] += val

dct = dict(dct) # get rid of default value

You could use Counter from collections to convert the tuples to countable key/values, then use reduce from functools to add them together:

from collections import Counter
from functools   import reduce

lst = [('Alex', 5), ('Addy', 7), ('Abdul', 2), ('Bob', 6), ('Carl', 8), ('Cal', 4)]

dst = reduce(Counter.__add__,(Counter({k[:1]:v}) for k,v in lst))

# Counter({'A': 14, 'C': 12, 'B': 6})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM