append() заменят элементы в списке, а не добавляет их
Есть код на Python
name_dict = {}
def thesaurus(*name):
for i in name:
first_vowel = i[0:1]
name_dict[first_vowel] = []
name_dict[first_vowel].append(i)
print(name_dict)
thesaurus('Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий")
На выходе должно получиться это:
{'Ю': ['Юрий', 'Юлия'], 'Н': ['Никита', 'Николай'], 'С': ['Савелий', 'Сергей']}
А получается это:
{'Ю': ['Юрий'], 'Н': ['Никита'], 'С': ['Савелий']}
Вместо того, чтобы добавить новый элемент в список, функция append() заменяет предыдущее значение с каждым новым циклом.
Хотелось бы понять причину этого явления, а заодно и получить правильный код.
P.S. Это мой первый вопрос на данном сайте, если я что-то сделал неправильно, не ругайте сильно!
Ответы (3 шт):
Вот рабочий вариант:
def my_func(names: list) -> dict:
name_dict = {}
for name in names:
name_dict[name[0]] = []
for name in names:
name_dict[name[0]].append(name)
return name_dict
my_func(['Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий"])
Ваша ошибка в том, что вы обнуляете список. Из за этого в него попадают только последние имена:
name_dict[first_vowel] = []
name_dict[first_vowel].append(i)
name_dict = {}
def thesaurus(*name):
for i in name:
first_vowel = i[0]
if name_dict.get(first_vowel) == None:
name_dict[first_vowel] = []
name_dict[first_vowel].append(i)
print(name_dict)
thesaurus('Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий")
Специально для иницилизации новых ключей есть dict.setdefault:
def thesaurus(*name):
name_dict = {}
for i in name:
name_dict.setdefault(i[0], []).append(i)
print(name_dict)
thesaurus('Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий")
{'Ю': ['Юлия', 'Юрий'], 'Н': ['Николай', 'Никита'], 'С': ['Сергей', 'Савелий']}
Другой инструмент collections.defaultdict:
import collections
def thesaurus(*name):
name_dict = collections.defaultdict(list)
for i in name:
name_dict[i[0]].append(i)
print(name_dict)
thesaurus('Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий")
defaultdict(<class 'list'>, {'Ю': ['Юлия', 'Юрий'], 'Н': ['Николай', 'Никита'], 'С': ['Сергей', 'Савелий']})
Если вы не хотите использовать ничего специального, проверяйте что ключ уже есть в словаре и, если его нет, создавайте:
def thesaurus(*name):
name_dict = {}
for i in name:
key = i[0]
if key not in name_dict:
name_dict[key] = []
name_dict[key].append(i)
print(name_dict)
thesaurus('Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий")
{'Ю': ['Юлия', 'Юрий'], 'Н': ['Николай', 'Никита'], 'С': ['Сергей', 'Савелий']}
И ещё один вариант, на крохотную долю быстрее. Я его меньше люблю из-за дублирования функциональности:
def thesaurus(*name):
name_dict = {}
for i in name:
key = i[0]
if key in name_dict:
name_dict[key].append(i)
else:
name_dict[key] = [i]
print(name_dict)
thesaurus('Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий")
{'Ю': ['Юлия', 'Юрий'], 'Н': ['Николай', 'Никита'], 'С': ['Сергей', 'Савелий']}
Все примеры выше смешивают частную функциональность (какие ключи и значения для телефонной книги) и общую (из пар ключ/значение сделать словарь списков). Будет правильно их разделить, общая функциональнось в функции multidict. thesaurus подготавливает данные и обращается к multidict:
def multidict(items):
md = {}
for k, v in items:
md.setdefault(k, []).append(v)
return md
def thesaurus(*name):
name_dict = multidict((i[0], i) for i in name)
print(name_dict)
thesaurus('Юлия', "Николай", "Юрий", "Сергей", "Никита", "Савелий")
{'Ю': ['Юлия', 'Юрий'], 'Н': ['Николай', 'Никита'], 'С': ['Сергей', 'Савелий']}