#dictionary #key #python
#словарь #Клавиша #python
Вопрос:
Я хочу получить все значения, связанные с ключом, в словаре. Иногда ключ содержит один словарь, иногда список словарей.
a = {
'shelf':{
'book':{'title':'the catcher in the rye', 'author':'j d salinger'}
}
}
b = {
'shelf':[
{'book':{'title':'kafka on the shore', 'author':'haruki murakami'}},
{'book':{'title':'atomised', 'author':'michel houellebecq'}}
]
}
Вот мой метод чтения названий каждой книги на полке.
def print_books(d):
if(len(d['shelf']) == 1):
print d['shelf']['book']['title']
else:
for book in d['shelf']:
print book['book']['title']
Это работает, но не выглядит аккуратно или по-питоновски. Цикл for завершается с ошибкой при единственном значении, отсюда if / else.
Можете ли вы улучшить это?
Комментарии:
1. Почему, о, почему ваши структуры данных не согласованы…
2. Отбросить средний dict, который в любом случае имеет только один ключ? И «полка» не была бы особенно актуальна только для одного элемента. Дзен Python: «Особые случаи недостаточно особенные, чтобы нарушать правила».
3. @Iganacio хаха, это не я. Данные поступают следующим образом из сервиса Yahoo.
Ответ №1:
Учитывая, что ваш код сломается, если у вас есть список с одним элементом (и я думаю, что так и должно быть), если вы действительно не можете изменить свою структуру данных, это немного более надежно и логично:
def print_books(d):
if isinstance(d['shelf'], dict):
print d['shelf']['book']['title']
else:
for book in d['shelf']:
print book['book']['title']
Ответ №2:
Почему не всегда сопоставлять ‘shelf’ со списком элементов, но в случае с одним элементом это … список с одним элементом? Тогда вы всегда сможете одинаково обращаться с каждой книжной полкой.
Ответ №3:
def print_books(d):
container = d['shelf']
books = container if isinstance(container, list) else [container['book']]
books = [ e['book'] for e in books ]
for book in books:
print book['title']
Ответ №4:
Я бы сначала согласовал входные данные, а затем перебрал все книги, даже если только одну.
def print_books(d):
books = d['shelf'] if type(d['shelf']) is list else [ d['shelf'] ]
for book in books:
print book['book']['title']
Я думаю, что это выглядит немного аккуратнее и по-питоновски, хотя некоторые могут возразить, что это не так эффективно, как ваш исходный код для создания массива с одним элементом и перебора его.