Поиск внутри кортежей, упакованных в список
Есть одна задача на python связанная с поисками внутри кортежей, упакованных в список. Понимаю смысл и алгоритм решения, но не хватает знаний языка. Изначальная задача такая, Вам дан список контактов, в котором каждый контакт представлен кортежем с именем и возрастом контакта. Завершите программу, чтобы принимать строку в качестве входных данных , искать имя в списке контактов и выводить возраст контакта в формате представленном ниже: Пример входных данных: John Пример выходных данных: John is 31
В случае если контакт не найден, программа выдает "Not found"
есть стартовый код:
contacts = [
('James', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
Я дописал туда свой код, вышло нечто такое
contacts = [
('james', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
res = input()
d=dict(contacts)
if res in (d.keys()):
a, b = contacts[i]
print(a + " " + "is" + " " + str(b))
else:
print("Not found")
В общем, не понимаю как позицию кортежа в списке contacts[i] вычислить, чтобы распаковать в a, b переменные верный кортеж. Если скажем подаю на ввод Amy, то i равно 1 и все работает если я i в ручную на 1 меняю, но вот как это сделать программными методами не понимаю. Буду признателен за правильное решение задачи этой, разными способами чтобы я мог понять как вообще с подобной темой работать и находить индекс нужный в листе внутри кортежей по вводу чего-либо.
Ответы (8 шт):
Просто нужно создать цикл for и перебрать список.
contacts = [
('james', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
res = input()
inList = False
for i in contacts:
if(i[0] == res):
inList = True
print("{0} is {1}".format(i[0], i[1]))
if(not inList):
print("Not found")
- Наличие ключа в словаре можно проверять просто через
res in d(безkeys()) - Если ключ в словаре найден, то он уже и есть ваше
a b- это значение по ключу (значение в словаре, соответствующее этому ключу), получаем из словаря черезd[res]
Всё, значения получены, индекс этих значений в списке вам и не нужен.
contacts = [
('james', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
res = input()
d=dict(contacts)
if res in d:
print(res + " is " + str(d[res]))
else:
print("Not found")
Еще можно через filter() и next() в списке найти искомый кортеж. filter() делает генератор, из которого next() тащит первое совпадение по имени. Дальше выводим либо форматированный результат, либо, если ничего не нашли, строку об отсутствии имени.
contacts = [
('james', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Amanda', 15),
('Bob', 18)
]
name = input('Введите имя')
Если у нас список из уникальных имен:
data = next(filter(lambda x: x[0] == name, contacts), None)
print('Имя: {}, возраст: {}'.format(*data) if data else 'Ничего не найдено')
Если список может иметь повторяющиеся имена:
data = list(filter(lambda x: x[0] == name, contacts))
print('\n'.join(['Имя: {}, возраст: {}'.format(*d) for d in data])) if data else print('Ничего не найдено')
Это кстати момент. Если есть повторяющиеся имена, то превращение в словарь их схлопнет по последнему значению:
contacts = [('Amanda', 15), ('Amanda', 65),]
станут
{'Amanda': 65}
contacts = [
('James', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
def get_age(name: str, contacts: list)->str:
result = "".join(f"{n} is {a}" for n, a in map(iter, contacts) if n is name)
if result:
return result
else:
return "Not found"
def main():
print(get_age("John", contacts))
print(get_age("Angela", contacts))
if __name__ == '__main__':
main()
contacts = [
('James', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
name = input()
for i in contacts:
if name in i:
print(i[0],'is',i[1])
else:
print("Not found")
contacts = [
('James', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)]
name = input()
data = next(filter(lambda x: x[0] == name, contacts), None)
print('{} is {}'.format(*data) if data else 'Not Found')
contacts = [
('James', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
d = dict(contacts)
name = input()
if name in d:
print(name, 'is', d[name])
else:
print('Not Found')
collections.namedtuple
В ряде случаев такой тип данных удобнее и эффективнее:
from collections import namedtuple
from rich import print, inspect
contacts = [
('James', 42),
('Amy', 24),
('John', 31),
('Amanda', 63),
('Bob', 18)
]
names, age = zip(*contacts)
Contacts = namedtuple(typename='Contacts', field_names=names)
# Переопределяем contacts
contacts = Contacts(*age)
inspect(contacts)
while name := input('Введите имя: '): # выход из цикла "" (пустая строка)
print('Not found' if not (age := getattr(contacts, name, False))
else f'{name} is {age}')
# try:
# print(f"{name} is {eval(f'contacts.{name}')}")
# except AttributeError:
# print("Not found")
else:
print('Введена "" - пустая строка, программа завершена.')
output:
╭─────────────── <class '__main__.Contacts'> ────────────────╮
│ Contacts(John, Bob, Amy, Amanda, James) │
│ │
│ ╭────────────────────────────────────────────────────────╮ │
│ │ Contacts(John=31, Bob=18, Amy=24, Amanda=63, James=42) │ │
│ ╰────────────────────────────────────────────────────────╯ │
│ │
│ Amanda = 63 │
│ Amy = 24 │
│ Bob = 18 │
│ James = 42 │
│ John = 31 │
╰────────────────────────────────────────────────────────────╯
Введите имя: John
John is 31
Введите имя: Anna
Not found
Введите имя:
Введена "" - пустая строка, программа завершена.
UPD:
Вот почему я считаю моё решение приемлемым:
- имя переменной
contacts; - структура данных укладывается в концепцию
data-класса; namedtuple— это простой способ создатьdata-класс;namedtupleпочти в два раза легче обычного класса
(т.к. не хранитdict-представление);- я не утверждаю что использование
dictне решает задачу получения значения по ключу
(моё предложение использоватьnamedtuple— вариация и вполне обоснованная).
К тому же для dict уже дан своевременный ответ, я лишь добавила яркий акцент к вопросу.