2013-09-11 6 views
1

У меня есть следующий код (который генерирует синтаксическую ошибку, кстати). Может ли кто-нибудь помочь мне исправить это, чтобы я мог получить версию, которая дает ожидаемый результат?Python - Присвоение нескольких значений словаря различным переменным в одной строке

al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
a, b, c = [i.a, i.b, i.c for i in al] 

Ожидаемый результат:

a = [1, 4, 7, 10] 
b = [2, 5, 8, 11] 
c = [3, 6, 9, 12] 
+0

Если вы действительно должны показывать ключи в коде. В таких ситуациях я обычно динамически строю dictionnairy и делаю импортный отпечаток; pprint mydict, Таким образом я могу создать pep8-совместимый dict – dusual

ответ

4

Если вы знаете, ключи заранее:

>>> al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
>>> a, b, c = [[d[key] for d in al] for key in 'abc'] # ('a', 'b', 'c') 
>>> a 
[1, 4, 7, 10] 
>>> b 
[2, 5, 8, 11] 
>>> c 
[3, 6, 9, 12] 

Если вы не знаете, ключи заранее:

>>> d = {key: [d[key] for d in al] for key in al[0]} 
>>> d 
{'a': [1, 4, 7, 10], 'c': [3, 6, 9, 12], 'b': [2, 5, 8, 11]} 
>>> a, b, c = map(d.get, 'abc') # OR map(d.get, ('a', 'b', 'c')) 
>>> a 
[1, 4, 7, 10] 
>>> b 
[2, 5, 8, 11] 
>>> c 
[3, 6, 9, 12] 
+0

Как насчет '[dict_.values ​​() для dict_ in al]' –

+1

@PauloScardine, он не производит то, что хочет OP. – falsetru

+0

Действительно, я забыл, что порядок не гарантируется в python dicts. –

0

Если вы 'интересуется однострочным, , и если вы гарантировать порядок и наличие ключей в dicts из al, то:

>>> al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
>>> dict(zip(al[0].keys(),zip(*[i.values() for i in al]))) 
{'a': (1, 4, 7, 10), 'c': (3, 6, 9, 12), 'b': (2, 5, 8, 11)} 
+2

Это немного глупо, так как вы не можете гарантировать порядок ключей в dict –

0

Вы могли бы сделать что-то вроде этого:

al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 

result={} 
for dic in al: 
    for key,val in dic.items(): 
     result.setdefault(key,[]).append(val) 

print result  
# {'a': [1, 4, 7, 10], 'c': [3, 6, 9, 12], 'b': [2, 5, 8, 11]} 
a,b,c=result['a'],result['b'],result['c'] 

print a,b,c 
# [1, 4, 7, 10] [2, 5, 8, 11] [3, 6, 9, 12] 

Если вы хотите, чтобы связать имена словарь для имен в текущем пространстве имен, вы можете сделать это:

al = [{'a': 1, 'b': 2, 'c': 3, 'd':4}, 
     {'a': 4, 'b': 5, 'c': 6}, 
     {'a': 7, 'b': 8, 'c': 9}] 

result={} 
for dic in al: 
    for k in dic: 
     result.setdefault(k,[]).append(dic[k]) 

print result  
# {'a': [1, 4, 7, 10], 'c': [3, 6, 9, 12], 'b': [2, 5, 8, 11], 'd': [4]} 

for k in result: 
    code=compile('{}=result["{}"]'.format(k,k), '<string>', 'exec') 
    exec code 

print a,b,c,d 
# [1, 4, 7, 10] [2, 5, 8, 11] [3, 6, 9, 12] [4] 
0

Попробуйте

a,b,c = [map(lambda x:x[ele], al) for ele in 'abc'] 
0
>>> al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
>>> from operator import itemgetter 
>>> a, b, c = zip(*map(itemgetter(*'abc'),(al))) 
>>> a 
(1, 4, 7, 10) 
>>> b 
(2, 5, 8, 11) 
>>> c 
(3, 6, 9, 12) 
1

Если ключи неизвестны, вы можете просто перенести данные и создать другой словарь транспонирования, который вы можете просто получить доступ к keys вместо создания отдельной переменных

>>> al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
>>> keys = al[0].keys() 
>>> #Given your list of dictionary 
>>> al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
>>> #determine the keys 
>>> keys = al[0].keys() 
>>> #and using itemgetter 
>>> from operator import itemgetter 
>>> #create a transpose dictionary 
>>> al_transpose = dict(zip(keys,zip(*map(itemgetter(*keys),al)))) 
>>> al_transpose['a'] 
(1, 4, 7, 10) 
>>> al_transpose['b'] 
(2, 5, 8, 11) 
>>> al_transpose['c'] 
(3, 6, 9, 12) 

Примечания Не Рекомендовано

Если вы действительно хотите создавать автономные переменные, вы можете сделать это, добавив словарь к locals

locals().update(al_transpose) 
>>> a 
(1, 4, 7, 10) 
>>> b 
(2, 5, 8, 11) 
>>> c 
(3, 6, 9, 12) 
0
>>> al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
>>> a, b, c = zip(*(sorted(x.values(), key=x.get) for x in al)) 
>>> a 
(1, 4, 7, 10) 
>>> b 
(3, 6, 9, 12) 
>>> c 
(2, 5, 8, 11) 
0

Это, как вам нужно изменить ваш метод

>>> al = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}, {'a': 10, 'b': 11, 'c': 12}] 
>>> a, b, c = zip(*((i['a'], i['b'], i['c']) for i in al)) 

Во-первых, вам нужно использовать i['a'] вместо i.a и т.д., так как a является ключом, а не атрибут

Так, чтобы дать вам

>>> [(i['a'], i['b'], i['c']) for i in al] 
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)] 

А, строки и столбцы неправильны.Они стандартный трюк, чтобы поменять местами строки и столбцы является zip(*A)

>>> zip(*[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)]) 
[(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)] 

Сочетание этих двух идей дает выражение в верхней части этого ответа

Более прямой подход вложенного списка постижение

>>> a, b, c = [[x[k] for x in al] for k in 'abc'] 

Если ключи не являются одиночными символами, вам необходимо записать их в качестве кортежа в длину

>>> a, b, c = [[x[k] for x in al] for k in ('a', 'b', 'c')] 
Смежные вопросы