4

There is a list given:

List= ["sugar:10", "coffee:23", "sugar:47", "salt:26"]

From that list I need to get dictionary:

Dict = {"sugar":57, "coffee":23, "salt":26}

I did some similar examples before, but with this one I only have general idea (to split list first) and if there is same key for 2 values I need to add them together.

Can someone pleas help and give me idea how to solve this?

cs95
  • 379,657
  • 97
  • 704
  • 746
noca951
  • 41
  • 2

5 Answers5

5

You can achieve this pretty easily with a defaultdict:

from collections import defaultdict

li = ["sugar:10", "coffee:23", "sugar:47", "salt:26"]

d = defaultdict(int)

for item in li:
    split_item = item.split(':')
    d[split_item[0]] += int(split_item[1])

print(d)
#  defaultdict(<class 'int'>, {'sugar': 57, 'coffee': 23, 'salt': 26})
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • Just for future readers, worth adding the difference between `dict` and `defaultdict` is that `defaultdict` returns the default of the item type if the key is not found - whereas `dict` gives a `KeyError`. –  Nov 27 '17 at 14:13
  • and defaultdict is faster in that aspect. – Jean-François Fabre Nov 27 '17 at 14:14
4

You can do fun things with Counters!

from collections import Counter

def f(x):
    x, y = x.split(':')
    return Counter({x : int(y)})

sum(map(f, lst), Counter())
Counter({'coffee': 23, 'salt': 26, 'sugar': 57})

If you're concerned about performance, a loop may be better suited.

r = Counter()
for x in lst:
    r.update(f(x))

r
Counter({'coffee': 23, 'salt': 26, 'sugar': 57})
cs95
  • 379,657
  • 97
  • 704
  • 746
  • 1
    that's brilliant. – Ma0 Nov 27 '17 at 13:53
  • 1
    It's good. I'm concerned about the performance of `sum`, which copies the dict not in-place (that's why you don't want use `sum` to flatten lists for instance. – Jean-François Fabre Nov 27 '17 at 13:55
  • `sum` doesn't do `result += current` but `result = result + current` to avoid modifying the intialization parameter, so it cannot be optimized: https://stackoverflow.com/questions/42593904/could-sum-be-faster-on-lists – Jean-François Fabre Nov 27 '17 at 13:57
  • 1
    @Jean-FrançoisFabre Okay, so not `__iadd__` but `__add__`... Here it is - https://github.com/python/cpython/blob/master/Lib/collections/__init__.py#L698 It seems a new Counter is initialised, but I don't know about its efficiency. You're right, loop may be better (added that in). – cs95 Nov 27 '17 at 14:01
  • Oops, the link earlier was to some other weird place... fixed that now. – cs95 Nov 27 '17 at 14:02
0
mydict={}
for i in List:
    splited=i.split(":")
    if(splited[0] in mydict):
        mydict[splited[0]]+=int(splited[1])
    else:
        mydict[splited[0]]=int(splited[1])
imox
  • 1,544
  • 12
  • 12
0

This should work as well.

from collections import defaultdict
d = defaultdict(int)
b = map(lambda x: (x[0], int(x[1])), [x.split(':') for x in li])
for k, v in b:
    d[k] += v

>>>d
defaultdict(<type 'int'>, {'coffee': 23, 'salt': 26, 'sugar': 57})
Sanindra
  • 70
  • 7
-1

Since Dict gets a list in its constructor, you can simple generate one out of your list on the fly.

Here it is:

>>> from collections import defaultdict
>>> l = ["sugar:10", "coffee:23", "sugar:47", "salt:26"]
>>> items = (i.split(":") for i in l)
>>> d = defaultdict(int)
>>> for i in items:
...     d[i[0]]+= int(i[1])
>>> dict(d)
{'coffee': 23, 'salt': 26, 'sugar': 57}
Tzury Bar Yochay
  • 8,798
  • 5
  • 49
  • 73
  • check your answer and @DeepSpace answer. You'll see that now they're exactly the same (you can flag my comment for deletion again, that won't improve your answer) – Jean-François Fabre Nov 27 '17 at 20:13