Возвращаемый словарь с одним измененным элементом

Скажем, у меня есть список словарей:

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

И я хочу выполнить операцию с картой, в которой я изменяю только одно значение в каждом словаре. Один из возможных способов сделать это – создать новый словарь, который просто содержит исходные значения вместе с измененными:

 >>> 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}] 

Это может стать непоколебимым, если словари имеют много предметов.

Другим способом может быть определение функции, которая копирует исходный словарь и изменяет только нужные значения:

 >>> 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}] 

Это, однако, требует написания отдельной функции и теряет элегантность лямбда-выражения.

Есть ли способ лучше?

Это работает (и совместимо с python2 и python3 1 ):

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

С учетом сказанного, я думаю, что чаще всего решения на основе lambda менее элегантны, чем
не- lambda контрагенты … Рациональное утверждение этого утверждения состоит в том, что я могу сразу же рассмотреть предложенное вами решение без lambda , и я точно знаю, что он делает. Решение на основе lambda которое я только что написал, задумалось бы, чтобы разобрать, а затем больше думать, чтобы понять …

1 Хотя, map даст вам итерируемый объект на python3.x, который не является списком …

Во-первых, запись функции не кажется мне неинтересной в первую очередь. Тем не менее, добро пожаловать в смелый новый мир Python 3.5 и PEP 448 :

 >>> d = [{'a': 2, 'b': 3, 'c': 4}, {'a': 5, 'b': 6, 'c': 7}] >>> d [{'b': 3, 'a': 2, 'c': 4}, {'b': 6, 'a': 5, 'c': 7}] >>> [{**x, 'b': x['b']+1} for x in d] [{'b': 4, 'a': 2, 'c': 4}, {'b': 7, 'a': 5, 'c': 7}] 

Из того, как ваша map ведет себя, ясно, что вы используете 2, но это достаточно легко исправить. 🙂

Вы можете использовать цикл for с вызовом update . Вот хакерский однострочный:

 dcts = [{'a': 2, 'b': 3, 'c': 4}, {'a': 5, 'b': 6, 'c': 7}] dcts = [d.update({'b': d['b']+1}) or d for d in dcts] 

Изменить: сохранить оригинальные дикты:

 from copy import copy dcts = [d.update({'b': d['b']+1}) or d for d in map(copy, dcts)]