2014-09-21 5 views
3

У меня есть словарь:Python с использованием format_map со словарем

People={ 
     'name':['john','peter'], 
     'age':[56,64] 
     } 

выход

'My name is {name[0]},i am {age[0]} old'.format_map(People) 

дает

'My name is john,i am 56 old' 

я хотел бы использовать format_map в цикле, чтобы получить:

'My name is {name[x]},i am {age[x]} old' 

для каждого элемента в словаре, как:

'My name is john,i am 56 old' 
'My name is peter,i am 64 old' 

но петля как:

['My name is {name[x]},i am {age[x]} old'.format_map(People) for x in range(0,len(People['name']))] 

дает:

KeyError: 'name' 

ответ

2

str.format_map принимает отображение. Вы не можете передать дополнительный аргумент.

В качестве альтернативы вы можете использовать str.format, но вложенность {..} внутри индексации ({0[name][{x}]}) не допускается.

Обход с использованием str.format и zip/map:

>>> people = { 
... 'name': ['john','peter'], 
... 'age': [56, 64] 
... } 

>>> ['My name is {}, i am {} old'.format(*x) 
... for x in zip(people['name'], people['age'])] 
['My name is john, i am 56 old', 'My name is peter, i am 64 old'] 

>>> ['My name is {}, i am {} old'.format(*x) 
... for x in zip(*map(people.get, ['name', 'age']))] 
['My name is john, i am 56 old', 'My name is peter, i am 64 old'] 
+0

@ PM2Ring, он работает очень хорошо для меня (оба в Python 2.7, Python 3.4). Смотрите это: https://asciinema.org/a/12330 – falsetru

+0

@ PM2Ring, версия 'map' будет более полезна, если в словаре есть более двух ключей. (Вам не нужно повторять 'people [...]') – falsetru

+0

@ PM2Ring, вы были совершенно правы. Извините за неправильную мысль. Спасибо, что указали это. – falsetru

0

Это может быть более понятным для вас сделать:

strs = ["My name is " + People['name'][i] + ",i am " + str(People['age'][i]) + " old" for i in len(People)] 
print(strs # ['My name is john,i am 56 old', 'My name is peter,i am 64 old']) 
+1

Я использовал бы len (people ['name']) 'вместо hard-coded 2 как OP. BTW, 'print' в Python 3.x - это функция. – falsetru

+0

Хорошие баллы! Спасибо @falsetru – alfasin

1

Вы можете сделать два прохода форматирования:

people = { 
    'name': ['John', 'Peter'], 
    'age': [56, 64] 
} 

for i in range(2): 
    'My name is {{name[{0}]}}, I am {{age[{0}]}} years old.'.format(i).format_map(people) 

#>>> 'My name is John, I am 56 years old.' 
#>>> 'My name is Peter, I am 64 years old.' 

...{{...}}... форматов ...{...}..., поэтому подходит второй звонок в format.

1

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

Одна возможность состоит в том, чтобы использовать список dicts, один Dict для каждого человека, например

new_people = [ 
    {'age': 56, 'name': 'john'}, 
    {'age': 64, 'name': 'peter'} 
] 

И тогда вы можете легко распечатать его, делая что-то вроде этого:

for d in new_people: 
    print('My name is {0}, I am {1} years old.'.format(d['name'], d['age'])) 

Выход :

My name is john, I am 56 years old. 
My name is peter, I am 64 years old. 

Не так сложно преобразовать существующих людей в список диктонов. Это, вероятно, более удобным для чтения, чтобы сделать это с парой for петель, но я это сделал с этого вложенного выражения список понимание/генератора:

new_people = [dict(t) for t in (((k,v[i]) for k,v in People.items()) for i in range(len(People['name'])))]

PS. Это соглашение в Python для использования имен нижнего регистра для обычных переменных. Имена, начинающиеся с буквы верхнего регистра, например People, обычно используются для занятий. У вас не есть, чтобы следовать этому соглашению, но это облегчает людям, читающим ваш код. Вы можете заметить, что в коде, который вы разместили выше, Люди светло-голубого цвета, это потому, что форматировщик SO-кода считает свое имя класса.

+0

OP использует Python 3.x. В Python 3.x нет 'dict.iteritems'. Это должны быть «предметы». – falsetru

+0

'len (People)' всегда будет возвращать 2, хотя в списках больше людей, потому что в данном словаре есть два ключа; 'len (People)' должен быть len (People ['name']) '. – falsetru

+1

Я бы сделал: 'new_people = [{k: v [i] для k, v в People.items()} для i в диапазоне (len (People ['name']))]' (используя dict-comprehension) – falsetru

Смежные вопросы