0

I've got the following input inp = [{1:100}, {3:200}, {8:300}] and I would like to convert it to the dictionary. I can do

dct = dict()  
for a in inp:  
    dct.update(a)

or I can do

_ = [dct.update(a) for a in inp]

But I would like to do something like:

map(dct.update, inp)
Alex S.
  • 974
  • 1
  • 13
  • 18
  • 4
    `map` operation is to transform a result and retrieve it so no. Like your uss of list comprehension which is to retieve result and not use statefull methods – azro Jun 20 '20 at 09:14
  • 2
    You *can* but you *shouldn't*. And the same applies to your list comprehension, you *shouldn't* be using it to call `dict.update`. Both `map` and comprehension constructs are functional programming constructs to express mapping/filtering operations on arbitrary iterables using pure-functions. Your functions shouldn't have side-effects, and they definitely shouldn't be used only for side-effects – juanpa.arrivillaga Jun 20 '20 at 09:16
  • 1
    You should not be ideally doing a list comprehension also for this task. Your first approach seems easy and probably the fastest of all. – Austin Jun 20 '20 at 09:16

4 Answers4

5

Method map builds a iterator, so the computes are made only when need it. So you need to force the computing, using a list for example

list(map(dct.update, inp))
print(dct)

But you shouldn't use either the list comprehension or the map operation that are here to produce values

You'd better keep your for-loop or a dict-comprehension

dct = {key:val for item in inp for key,val in item.items()}
azro
  • 53,056
  • 7
  • 34
  • 70
1

Why use map for this task?

If you want to solve it in one line you can just do:

dct={k:v for x in inp for k,v in x.items()}
Giuseppe
  • 658
  • 1
  • 6
  • 14
1

With using Chain Map:

from collections import ChainMap

inp = [{1: 100}, {3: 200}, {8: 300}]
data = dict(ChainMap(*inp))
grim
  • 9
  • 1
0

What you want is reduce, not map. map creates a sequence by applying a function to each element of the given sequence, whereas reduce accumulates an object over the sequence.

from functools import reduce
inp = [{1:100}, {3:200}, {8:300}]
dct = {}
reduce(lambda d1, d2: (d1.update(d2) or d1), inp, dct)
{1: 100, 3: 200, 8: 300}

This lambda part may look tricky. What this does is to create a function that updates a dict and returns the dictionary itself. This is because reduce expects the accumulating function returns the updated object while dict.update() returns None. Since None is interpreted as False, the or operator returns the second variable, which is the updated dictionary.

This or trick is credited to @kostya-goloveshko in this thread: Why doesn't a python dict.update() return the object?

Kota Mori
  • 6,510
  • 1
  • 21
  • 25
  • Thank you, indeed! I was interested in this kind of tooling, though the one line answer above is indeed more useful/practical for such a task. – Alex S. Jun 20 '20 at 09:39
  • Tricky, and very messy. I'm heavily against using NoneType falsity in such construct. – goteguru Jun 20 '20 at 09:44
  • 1
    @goteguru it's also another example of using imperative code in a functional construct. Hence the messiness. – juanpa.arrivillaga Jun 20 '20 at 09:45