#python-3.x #algorithm
#python-3.x #алгоритм
Вопрос:
Простите меня, если тема уже существует, но я ее не нашел…
У меня есть 3 списка dict :
list_1 = [
{'name': "Leonardo Di Caprio", 'films': ["The revenant", "Titanic", "The wold of Wall Street"]},
{'name': "Will Smith", 'films': ["I am a legend", "The pursuit of happyness"]},
{'name': "Robert De Niro", 'films': ["Taxi driver", "The godfather"]}
]
list_2 = [
{'name': "Leonardo Di Caprio", 'films': ["Titanic", "The revenant", "The wold of Wall Street"]},
{'name': "Will Smith", 'films': ["I am a legend", "The pursuit of happyness", "Aladdin"]},
{'name': "Robert De Niro", 'films': ["Taxi driver", "The godfather"]}
]
list_final = [
{'name': "Tom Hanks", 'films': ["Forest Gump", "Cast Away", "Greyhound"]},
{'name': "Will Smith", 'films': ["I am a legend", "The pursuit of happyness"]},
{'name': "Tom Cruise", 'films': ["Top Gun", "Mission impossible"]},
{'name': "Robert De Niro", 'films': ["Taxi driver", "The godfather"]},
{'name': "Leonardo Di Caprio", 'films': ["Titanic", "The revenant", "The wold of Wall Street"]},
{'name': "Harrison Ford", 'films': ["Blade Runner", "Indiana Jones"]},
{'name': "Morgan Freeman", 'films': ["Seven"]}
]
Я хотел бы создать функцию, которая принимает 2 списка dict в качестве параметров и возвращает логическое значение. Цель состоит в том, чтобы проверить list_1
, содержится ли в list_final
.
Под «содержится» я имею в виду :
- В каждом актере
list_1
должны присутствовать имена froomlist_final
(независимо от порядка) - Все фильмы, в которых играет определенный актер,
list_1
должны присутствовать вlist_final
У меня есть функциональный код :
def isContained(l1 : List[Dict[str, List]], l_final: List[Dict[str, List]]) -> bool:
for elem in l1:
findOccurence = False
for element in l_final:
if elem['name'] == element['name'] and all(item in element['films'] for item in elem['films']):
findOccurence = True
if not findOccurence:
return False
return True
print(isContained(list_1, list_final)) # True
print(isContained(list_2, list_final)) # False
print(isContained(list_1, list_2)) # True
print(isContained(list_2, list_1)) # False
Вывод :
root@root:/tmp/TEST_PYTHON$ python3 main.py
True
False
True
False
Итак, это работает, но я уверен, что есть другой способ закодировать его в более оптимизированном алгоритме.
Что меня беспокоит, так это повторение всего окончательного списка столько раз, сколько у меня итераций в list_1
Есть предложения?
Комментарии:
1. Обратите внимание, что слово «функциональный» имеет очень специфическое значение в программировании. Я бы не стал описывать ваш код как «функциональный».
2. Это правда, я хотел сказать «рабочий» код, спасибо за совет. Это лучше?
Ответ №1:
После небольшой корректировки ваших структур данных, чтобы сделать работу немного более эффективной…
Это можно сделать, используя оператор intersect amp;
и метод issubset для set .
list_1 = {
"Leonardo Di Caprio":{"The revenant", "Titanic", "The wold of Wall Street"},
"Will Smith":{"I am a legend", "The pursuit of happyness"},
"Robert De Niro": {"Taxi driver", "The godfather"}
}
list_2 = {
"Leonardo Di Caprio": {"Titanic", "The revenant", "The wold of Wall Street"},
"Will Smith": {"I am a legend", "The pursuit of happyness", "Aladdin"},
"Robert De Niro": {"Taxi driver", "The godfather"}
}
list_final = {
"Tom Hanks": {"Forest Gump", "Cast Away", "Greyhound"},
"Will Smith": {"I am a legend", "The pursuit of happyness"},
"Tom Cruise": {"Top Gun", "Mission impossible"},
"Robert De Niro": {"Taxi driver", "The godfather"},
"Leonardo Di Caprio": {"Titanic", "The revenant", "The wold of Wall Street"},
"Harrison Ford": {"Blade Runner", "Indiana Jones"},
"Morgan Freeman": {"Seven"}
}
def isContained(l1, l_final) -> bool:
if (set(l1.keys()).issubset(set(l1.keys()))):
for key in set(l1.keys()) amp; set(l_final.keys()):
if (not (l1[key].issubset(l_final[key]))):
return False;
return True;
После комментариев от @Stef решение было исправлено и теперь:
def isContained(l1, l_final) -> bool:
if (set(l1.keys()).issubset(set(l_final.keys()))):
for key in set(l1.keys()) amp; set(l_final.keys()):
if (not (l1[key].issubset(l_final[key]))):
return False;
else:
return False
return True;
Для подтверждения правильного выполнения первого условия требуется дополнительное условие проверки…
list_3 = {"Sigourney Weaver": {"Aliens"}}
И условие:
print(isContained(list_3, list_final)) # False
Комментарии:
1.
set(l1.keys()).issubset(set(l1.keys()))
Я думаю, что один из них должен бытьl_final
, а неl1
?2. Существует и другая ошибка — если условие внешнего
if
равно false , тоisContained
возвращаетсяTrue
. НоFalse
в этом случае он должен вернуться, верно?3. Вы могли бы переписать все это как
def isContained(l1, l2): return (set(l1.keys()).issubset(l2.keys())) and all(set(v).issubset(l2[k]) for k,v in l1.items())
4. Вы также можете завершить свой ответ, предоставив функцию для преобразования формата списка OP в формат вашего dict:
def dict_of_list(l): return {x['name']: set(x['films']) for x in l}
5. Я не вижу точки оператора пересечения
amp;
в цикле for; на данный момент вы уже проверили, чтоl1.keys()
это подмножествоl_final.keys()
, поэтому из этого следует, чтоset(l1.keys()) amp; set(l_final.keys()) == set(l1.keys())
.