получить ключ-значение по значению из списка
Придумал себе задачку, чтобы практиковаться с листами и словарями и запутался напрочь.
Есть словарь из людей и инструментов.
{'Ivan ': ['guit', 'bass'], 'Stas': ['guit', 'bass', 'vox', 'keys'], 'Nick': ['drums', 'keys'], 'Sasha': ['vox', 'keys', 'guit']}
Нужно создать новый словарь где есть только три человека с тремя не повторяющимися инструментами. Желаю получить что-то вроде
{'Ivan ': ['guit'], 'Stas': ['bass'], 'Nick': ['drums']
Например, я делаю список существующих инструментов
['guit', 'bass', 'vox', 'synth', 'drums']
Рандом выбирает из списка инструмент и вот тут я не понимаю как по этому значению найти человека (любого) с этим инструментом и добавить в новый словарь
Ответы (2 шт):
Ну, если я вас правильно понял, делается это так:
import random
instruments = ['guit', 'bass', 'vox', 'synth', 'drums']
musicians = {
'Ivan ': ['guit', 'bass'],
'Stas': ['guit', 'bass', 'vox', 'synth'],
'Nick': ['drums', 'synth'],
'Sasha': ['vox', 'synth', 'guit']
}
triple = random.sample(instruments, 3)
result = {}
for el in triple:
for k, v in musicians.items():
if el in v and k not in result:
result[k] = el
break
print(result)
Функция random.sample() выбирает из переданного списка три случайных неповторяющихся значения.
Далее простая проверка. Для каждого интересующего нас инструмента проверяем, кто из людей им владеет и нет ли такого человека у нас в результирующем списке.
Однако, как правильно заметил @GrAnd, этот алгоритм может выдавать в результате неполную тройку музыкантов, даже если такая существует.
Я вижу два решения этой проблемы. Во-первых, можно отсортировать словарь musicians по возрастанию ключей, хотя это может не помочь.
Во-вторых, можно находить все возможные комбинации подходящих музыкантов и выбирать самую длинную.
У меня получилось такое решение. Я использовал рекурсию чтобы в случае необходимости точно перебрать все варианты и найти комбинацию (или не найти) когда для всех инструментов найдутся музыканты.
import random
def solver(persons, inst_lst):
for i, inst in enumerate(inst_lst):
# список оставшихся инструментов
other_inst_lst = inst_lst[:i] + inst_lst[i+1:]
# итерируемся по людям у кого есть этот инструмент
for name in dict(filter(lambda el: inst in el[1], persons.items())):
# исключаем этого человека из дальнейшего поиска
other_persons = dict(filter(lambda el: name != el[0], persons.items()))
if other_inst_lst:
if other_persons:
# ищем пару человек-инструмент в оставшихся людях и инструментах
res = solver(other_persons, other_inst_lst)
# если нашли, то добавляем к результату текущую пару человек-инструмент
if res: return [(name, inst)] + res
else:
# это был последний инструмент - возвращаем текущую пару
return [(name, inst)]
return None
PERSONS = {'Ivan' : ['guit' , 'bass'],
'Stas' : ['guit' , 'bass', 'vox', 'keys'],
'Nick' : ['drums', 'keys'],
'Sasha': ['vox' , 'keys', 'guit']}
instruments = set(item for sublist in PERSONS.values() for item in sublist)
inst_choise = random.sample(instruments, 3)
print("Инструменты:", inst_choise)
print("Группа:", solver(PERSONS, inst_choise))