3

suppose we have a list of dictionaries like this:

l = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 5, 'b': 6}]

I want to increment the value of each a-key by one. This is easy to achieve with a loop like this:

for dictionary in l:
  dictionary['a'] += 1

But is it possible to do that with a combination of map and lambda as well? It has to be something like this:

l = map(lambda x: x+1, l)

But I don't know how to specify the a-key in the lambda. lambda x['a'] didn't work. Any suggestions?

Thanks in advance!

levi
  • 22,001
  • 7
  • 73
  • 74
Flo1895
  • 429
  • 1
  • 6
  • 15
  • 2
    Probably not a good idea. Why create a list if all you want is the side effects of mutating the dictionaries? This is wasteful of memory. See this: http://stackoverflow.com/q/14633298/4996248 – John Coleman Nov 02 '15 at 14:31
  • Why do you want to use `map` here? This issue could be easily solved in imperative way (your example with `for`), but using functional paradigm requires strong support for persistent data structures, which Python does not have. In short: instead of changing one value per dictionary, you have to copy each dictionary and replace one value in it. Does not look like a Pythonic-way – awesoon Nov 02 '15 at 14:33
  • map(lambda x:x['a']+1 , l) print l – Prashant Shukla Nov 02 '15 at 14:34
  • It is more like a theoretical playing around without a useful application in mind. But map(lambda x:x['a']+1 , l) print l doesn't work. It returns only a list of the updated entries, i.e. [2, 4, 6]. I want a list like this: [{'a': 2, 'b': 2}, {'a': 4, 'b': 4}, {'a': 6, 'b': 6}] – Flo1895 Nov 02 '15 at 14:46

3 Answers3

1
l = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 5, 'b': 6}]
l = map(lambda x: {'a':x['a']+1,'b':x['b']}, l)
print l #in python 3 you need convert map to list list(l)
>>>[{'a': 2, 'b': 2}, {'a': 4, 'b': 4}, {'a': 6, 'b': 6}]
levi
  • 22,001
  • 7
  • 73
  • 74
  • Hmm, ok, it is basically like copying the dictionaries and modifying the entries accordingly. Thanks for sharing the idea. :) – Flo1895 Nov 02 '15 at 15:09
  • 1
    Note, on python3.x, `map` no longer consumes the input iterable until it needs to (e.g. when you decide to actually iterate over the result). That _could_ cause issues with something like this. – mgilson Nov 02 '15 at 15:55
  • @mgilson right, you need to convert it to a list. I added – levi Nov 02 '15 at 16:39
1

I agree with @John-Colemans that this is not a good idea, but you could implement it like this:

l = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 5, 'b': 6}]
l = map(lambda x:{'a':x['a']+1,'b':x['b']} , l) 
print l

Gives:

[{'a': 2, 'b': 2}, {'a': 4, 'b': 4}, {'a': 6, 'b': 6}]

This would of course not work if you get entries like {'a':1,'c':2}

Alex
  • 21,273
  • 10
  • 61
  • 73
  • Yes, it seems like all solutions need the structure of the dictionary and suppose that each dictionary looks the same. – Flo1895 Nov 02 '15 at 15:12
0

As long as we're clear that this isn't a practical thing, you could do it in Python 3 with an anonymous function which returns a dictionary comprehension:

l = list(map(lambda d: {k:d[k]+1 if k == 'a' else d[k] for k in d},l))

This approach works for any number of keys besides 'a'.

l evaluates to:

[{'b': 2, 'a': 2}, {'b': 4, 'a': 4}, {'b': 6, 'a': 6}]

but note that this is a brand-new list of brand-new dictionaries.

If you wanted to keep l itself unchanged and merely mutate the dictionaries, and you don't want to create a list simply to discard it, you could evaluate the following (which will work in Python 2 but with Python 3's lazy iterators never creates any list in memory):

assert(all(map(lambda x: not x , map(lambda d : d.update({'a':d['a']+1}),l))))

This produces no output but once you evaluate it you can verify that the dictionaries have been modified but no copies have been formed and only the value of the a keys have been changed. Needless to say, this is much less readable than the 2-line for loop.

John Coleman
  • 51,337
  • 7
  • 54
  • 119