juniper- juniper- - 6 months ago 11
Python Question

Return dictionary with one changed element

Let's say I have a list of dictionaries:

>>> d = [{'a': 2, 'b': 3, 'c': 4}, {'a': 5, 'b': 6, 'c': 7}]


And I want to perform a map operation where I change just one value in each dictionary. One possible way to do that is to create a new dictionary which simply contains the original values along with the changed ones:

>>> map(lambda x: {'a': x['a'], 'b': x['b'] + 1, 'c': x['c']}, d)
[{'a': 2, 'c': 4, 'b': 4}, {'a': 5, 'c': 7, 'b': 7}]


This can get unruly if the dictionaries have many items.

Another way might be to define a function which copies the original dictionary and only changes the desired values:

>>> def change_b(x):
... new_x = x.copy()
... new_x['b'] = x['b'] + 1
... return new_x
...
>>> map(change_b, d)
[{'a': 2, 'c': 4, 'b': 4}, {'a': 5, 'c': 7, 'b': 7}]


This, however, requires writing a separate function and loses the elegance of a lambda expression.

Is there a better way?

Answer

This works (and is compatible with python2 and python31):

>>> map(lambda x: dict(x, b=x['b']+1), d)
[{'a': 2, 'c': 4, 'b': 4}, {'a': 5, 'c': 7, 'b': 7}]

With that said, I think that more often than not, lambda based solutions are less elegant than
non-lambda counterparts... The rational behind this statement is that I can immediately look at the non-lambda solution that you proposed and I know exactly what it does. The lambda based solution that I just wrote would take a bit of thinking to parse and then more thinking to actually understand...

1Though, map will give you an iterable object on python3.x that isn't a list...

Comments