Как сделать поиск по словарю в python3?
Есть словарь вида:
emploers = {'id1':{'name':"Джон", 'Familia':"Трамп", 'Otchestvo':"Дональдович", 'Telefon':"33-33-33"},'id2':{'name':"Владимир", 'Familia':"Путин", 'Otchestvo': "Владимирович", 'Telefon':"8(912)911911911"}}
Мне нужно при вводе значения name вывести скажем значение Telefon.
Делаю вот так:
for search_emploers in emploers: name1 = input("Введите имя ") if emploers[search_emploers]['name'] == name1: print(emploers[search_emploers]['Telefon']) else: print('нет такого значения')
Но мне выводит поиск только по первому словарю а потом еще раз задает тот же вопрос.
Подскажите как реализовать данный функционал, я начинающий в Python3.
Решение в стиле Pandas:
In [99]: import pandas as pd In [100]: df = pd.DataFrame(emploers).T In [101]: df Out[101]: Familia Otchestvo Telefon name id1 Трамп Дональдович 33-33-33 Джон id2 Путин Владимирович 8(912)911911911 Владимир In [102]: df.query("name in ['Джон']") Out[102]: Familia Otchestvo Telefon name id1 Трамп Дональдович 33-33-33 Джон In [103]: df.query("name in ['Джон']")['Telefon'] Out[103]: id1 33-33-33 Name: Telefon, dtype: object In [104]: df.query("name in ['Джон']")[['Familia', 'Telefon']] Out[104]: Familia Telefon id1 Трамп 33-33-33
PS эту задачу можно легко решить без применения дополнительных модулей. Данный ответ просто демонстрирует легкость обработки и поиска информации при помощи Pandas.
Чтобы реализовать jq
команду, которая печатает телефон по заданному имени из input.json
файла:
$ jq -r '.. | select(.name? == "Владимир") | .phone' input.json
на Питоне достаточно input()
поднять из цикла наверх в вашем коде:
#!/usr/bin/env python3 name = input('Введите имя') for person in presidents.values(): if person['name'] == name: print(person['phone'])
где input.json
файл, переданный в командной строке, загружен в presidents
словарь:
import fileinput import json data = "".join(fileinput.input(openhook=fileinput.hook_encoded("utf-8"))) presidents = json.loads(data)
Чтобы найти объекты с указанным именем на любом уровне вложенности (как это приведённая выше jq
команда делает), можно рекурсивное решение использовать:
def get_all_dicts(seq_or_mapping, predicate): if hasattr(seq_or_mapping, 'values'): # mapping if predicate(seq_or_mapping): yield seq_or_mapping # found values = seq_or_mapping.values() else: # sequence values = seq_or_mapping # check nested collections for value in values: if isinstance(value, (dict, list)): yield from get_all_dicts(value, predicate) # recursion
См. Как получить все значения по ключу из массива. Пример:
nested = {'results': [{'name': 'Trinity', 'phone': '312-555-0690'}]} for d in get_all_dicts(nested, lambda d: d.get('name') == 'Trinity'): print(d['phone']) # -> 312-555-0690
[/apcode]
Сделайте так:
employer = {'id1': {'name': "Джон", 'Familia': "Трамп", 'Otchestvo': "Дональдович", 'Telefon': "33-33-33"}, 'id2': {'name': "Владимир", 'Familia': "Путин", 'Otchestvo': "Владимирович", 'Telefon': "8(912)911911911"}} name1 = input("Введите имя: ") flag = True for search_emploers in employer: if employer[search_emploers]['name'] == name1: print(employer[search_emploers]['Telefon']) flag = False if flag: print('нет такого значения')
Тут просто ввод данных нужно было вынести из цикла.
Лично я бы реализовал это так:
flag = True name_id1 = input("Введите имя: ") for i in employer: if employer.get(i).get('name').upper() == name_id1.upper(): print(employer.get(i).get('Telefon')) flag = False if flag: print('Имя не найдено')
Метод upper
(переводит строку в верхний регистр) добавил для того, чтобы избежать несовпадений в регистре.
Вывод нескольких значений:
if employer[search_emploers]['name'].upper() == name1.upper(): print(employer[search_emploers]['name'], employer[search_emploers]['Familia'])
Перебор и сравнение:
def my_find(employer, name): for k, v in employer.items(): if v['name'] == name: print(v['Telefon']) return print('Не найдено: "{}"'.format(name)) employer = { 'id1': { 'name': "Джон", 'Familia': "Трамп", 'Otchestvo': "Дональдович", 'Telefon': "33-33-33" }, 'id2': { 'name': "Владимир", 'Familia': "Путин", 'Otchestvo': "Владимирович", 'Telefon': "8(912)911911911" } } name_id1 = input("Введите имя: ") my_find(employer, name_id1)
In [8]: def _get(dct, name, value): ...: result = list(filter(lambda x: x.get('name') == name, dct.values())) ...: return result[0][value] if result else False ...: In [9]: _get(emploers, 'Джон', 'Telefon') Out[9]: '33-33-33' In [10]: _get(emploers, 'Karl', 'Telefon') Out[10]: False
emploers = {'id1': {'name': "Джон", 'Familia': "Трамп", 'Otchestvo': "Дональдович", 'Telefon': "33-33-33"}, 'id2': {'name': "Владимир", 'Familia': "Путин", 'Otchestvo': "Владимирович", 'Telefon': "8(912)911911911"}, 'id3': {'name': "Владимир", 'Familia': "Иванов", 'Otchestvo': "Владимирович", 'Telefon': None}} def get(emploers=emploers, **keys): ki = keys.items() for i in emploers: dt = emploers[i] if all((dt[k] == v) for (k, v) in ki): yield dt g = get(Otchestvo="Дональдович") print(next(g)['Telefon']) # 33-33-33 g = get(name="Владимир", Otchestvo="Владимирович") print(next(g)['Familia']) # Путин print(next(g)['Familia']) # Иванов