2017-01-30 2 views
3

У меня есть два списка, один содержащие Int значения:Что такое вещий способ настройки полей в Словаре в списке

values = [5,10,15,20] 

Другой список dicts:

dicts = [{'a':0, 'b':0, 'c':0}, 
     {'a':0, 'b':0, 'c':0}, 
     {'a':0, 'b':0, 'c':0}, 
     {'a':0, 'b': 0, 'c':0}] 

I хотите получить первое значение из списка значений и установить поле «a» первого dict со значением, исходящим из списка «values» и так далее. Другими словами, выход должен быть следующим:

dicts = [{'a':5, 'b':0, 'c':0}, 
     {'a':10, 'b':0, 'c':0}, 
     {'a':15, 'b':0, 'c':0}, 
     {'a':20, 'b': 0, 'c':0}] 

Что такое Pythonic способ сделать это?

+1

насчет '' b' и c' ключи? будут ли их значения оставаться 0? –

+0

Ваш синтаксис для словарей был неправильным. –

ответ

4

Ну, вы можете использовать zip для установки значения для 'a' для каждого словаря. Что-то вроде:

for dic,val in zip(dicts,values): 
    dic['a'] = val 

Или положить его в однострочника:

for dic,val in zip(dicts,values): dic['a'] = val 

Обратите внимание, что нет никакой разницы с предыдущим фрагментом кода. Это зависит от того, что нравится вашему глазу.

Мы здесь обновление словари: мы не создаем копии и т. Д. Это важное различие, поскольку переменные, которые могут ссылаться на указанные словари, отражают изменения, которые мы делаем.

zip(..) принимает в качестве входных данных последовательности или более итерируемых (здесь dicts и values) и генерирует кортежи элементов этих итерируемые. Так он испускает:

(values[0],dicts[0]), (values[1],dicts[1]), ... 

Теперь мы делаем кортежа распаковке: мы унифицировать val и dic с одним из values и один из dicts. Поэтому для каждого из кортежей мы устанавливаем значение dic['a']. Тест

консоли:

$ python3 
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> values = [5,10,15,20] 
>>> dicts = [{'a':0, 'b':0, 'c':0}, 
...   {'a':0, 'b':0, 'c':0}, 
...   {'a':0, 'b':0, 'c':0}, 
...   {'a':0, 'b': 0, 'c':0}] 
>>> for dic,val in zip(dicts,values): dic['a'] = val 
... 
>>> dicts 
[{'b': 0, 'c': 0, 'a': 5}, {'b': 0, 'c': 0, 'a': 10}, {'b': 0, 'c': 0, 'a': 15}, {'b': 0, 'c': 0, 'a': 20}] 
+6

Действительно, не ставьте его на одну строку под ошибочным убеждением, что оно несет какую-то выгоду. Это не. – chepner

+0

@chepner: ну для парсера Python нет никакой разницы вообще, насколько я знаю. Но это более компактно. –

+1

Большое спасибо за ответ. Это действительно то, что я искал. –

1

Для ради вещий однострочника (хотя я настоятельно рекомендуем предпочесть ответ Виллема для ясности/читаемость):

dicts = [{key: val if key != 'a' else z_val 
      for key, val in d.items()} for d, z_val in zip(dicts, values)] 

dicts 
Out[5]: 
[{'a': 5, 'b': 0, 'c': 0}, 
{'a': 10, 'b': 0, 'c': 0}, 
{'a': 15, 'b': 0, 'c': 0}, 
{'a': 20, 'b': 0, 'c': 0}] 

Edit: Удален резервный ifelse для ключей словаря.

+0

Помните, что это сделает ** копию ** словаря. Это может быть важным отличием, поскольку другие переменные, ссылающиеся на словари * old *, не будут отражать изменения. (Я не говорю, что это проблема, но, возможно, стоит отметить это). –

+0

@StefanPochmann Я просто смотрел на это ... Немного избыточно, да? Спасибо, что указали это. – blacksite

0

Попробуйте этот код:

values = [5,10,15,20] 
dicts = [{'a':0, 'b':0, 'c':0}, 
     {'a':0, 'b':0, 'c':0}, 
     {'a':0, 'b':0, 'c':0}, 
     {'a':0, 'b': 0, 'c':0}] 

res1 = dict(zip(dicts[0],zip(*[d.values() for d in dicts])))# tronspose a list of dicts /// res1 = {'a': (0, 0, 0, 0), 'c': (0, 0, 0, 0), 'b': (0, 0, 0, 0)} 
res1['a'] = values 
res = [dict(zip(res1,t)) for t in zip(*res1.values())]# tronspose res1