Поиск внутри кортежей, упакованных в список

Есть одна задача на 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")

→ Ссылка
Автор решения: insolor
  1. Наличие ключа в словаре можно проверять просто через res in d (без keys())
  2. Если ключ в словаре найден, то он уже и есть ваше a
  3. 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")
→ Ссылка
Автор решения: Andy Pavlov

Еще можно через 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()
→ Ссылка
Автор решения: Фeдop Hyeмывайкин
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")
→ Ссылка
Автор решения: Leroy
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')

→ Ссылка
Автор решения: Natalia
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')
→ Ссылка
Автор решения: AnnaBazueva

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:

Вот почему я считаю моё решение приемлемым:

  1. имя переменной contacts;
  2. структура данных укладывается в концепцию data-класса;
  3. namedtuple — это простой способ создать data-класс;
  4. namedtuple почти в два раза легче обычного класса
    (т.к. не хранит dict-представление);
  5. я не утверждаю что использование dict не решает задачу получения значения по ключу
    (моё предложение использовать namedtupleвариация и вполне обоснованная).

К тому же для dict уже дан своевременный ответ, я лишь добавила яркий акцент к вопросу.

→ Ссылка