Когда я использую цикл с одной строкой в Python, я получаю два разных значения в зависимости от выбранного мной процесса (Назначение и добавление процессов). Я хочу понять разницу и то, как они работают. В следующих двух примерах я пытаюсь написать программу, которая возвращает список, содержащий только те элементы, которые являются общими для списков (без дубликатов).
Первая программа с добавлением и я получаю правильный результат:
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
def common_in_two_lists(list1, list2):
re_list = []
[re_list.append(val1) for val1 in list1 for val2 in list2 if val1==val2 and val1 not in re_list]
return re_list
После вызова функции и списка выходных данных:
l = common_in_two_lists(a, b)
print(l)
и выход:
[1, 2, 3, 5, 8, 13]
Но когда я использую метод назначения как следующий, я получаю неправильный ответ:
def common_in_two_lists(list1, list2):
re_list = []
re_list = [val1 for val1 in list1 for val2 in list2 if val1==val2 and val1 not in re_list]
return re_list
l = common_in_two_lists(a, b)
print(l)
и выход:
[1, 1, 2, 3, 5, 8, 13]
Любой может научить меня понимать, как это происходит по-разному?
Чтобы понять это, вам нужно разбить код на более простую форму. Взяв первый пример.
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
def common_in_two_lists1(list1, list2):
re_list = []
for val1 in list1:
for val2 in list2:
if val1 == val2 and val1 not in re_list:
re_list.append(val1)
print(re_list)
return re_list
l = common_in_two_lists1(a, b)
ВЫХОД
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 5]
[1, 2, 3, 5, 8]
[1, 2, 3, 5, 8, 13]
Вы можете видеть, что re_list
значение каждый раз. И []
вы положили для первого примера, бесполезны.
Перейдем к вашему второму примеру. Если вы проверите тип выражения, вы найдете его генератором.
re_list = print(type(val1 for val1 in list1 for val2 in list2 if val1 == val2 and val1 not in re_list))
<class 'generator'>
И выражение генератора оценивается только тогда, когда вы пытаетесь извлечь значение, что объясняет, почему вы получаете дубликат 1 в этом коде. Потому что в выражении re_list
пуст при создании генератора.
Наконец, придя к вашему решению:
Я пытаюсь написать программу, которая возвращает список, содержащий только те элементы, которые являются общими для списков (без дубликатов).
Вы должны следовать рекомендациям Jon Clements и применять его с помощью набора
вы должны взглянуть на множества... например: list (set (a).intersection(b))
re_list = []
из моего первого примера. Почему?
re_list = []
не бесполезен, он очень необходим, поскольку требуется для объявления. Вы не можете добавить в список, пока не объявите его.
Во втором примере re_list пуст к моменту создания нового списка, поэтому val1 not in re_list
всегда false. В первом вы создаете список того, что возвращается re_list.append()
(None
, как я помню) и назначить его в никуда, модифицируя re_list
.
Кстати, почему бы вам не использовать set()
для получения списка уникальных элементов?
set()
для получения списка уникальных элементов?
def common_in_two_lists(list1, list2):
re_list = []
[re_list.append(val1) for val1 in list1 for val2 in list2 if val1==val2 and val1 not in re_list]
return re_list
эквивалентно:
def common_in_two_lists(list1, list2):
re_list = []
for val1 in list1:
for val2 in list2:
if val1==val2 and val1 not in re_list:
re_list.append(val1)
return re_list
тогда как второй метод:
def common_in_two_lists(list1, list2):
re_list = []
re_list = [val1 for val1 in list1 for val2 in list2 if val1==val2 and val1 not in re_list]
return re_list
эквивалентно
def common_in_two_lists(list1, list2):
re_list_old = []
re_list = []
for val1 in list1:
for val2 in list2:
if val1==val2 and val1 not in re_list_old: #note re_list_old here
re_list.append(val1)
return re_list
Стоит заметить, что со вторым методом вы не проверяете дубликаты в конечном списке, потому что каждый раз, когда вы проверяете пустой список при выполнении val1 not in re_list
Оба способа работают в O(n**2)
сложности времени, используя наборы:
l = list(set(a) & set(b))
это более эффективно и проще, так как вы можете сделать это со средней временной сложностью O(min(len(a), len(b))
(худший случай - O(len(a)*len(b))
).
re_list = []
не требуется, так как следующая строка создает новый список в любом случае.re_list = [val1 for val1 in list1 for val2 in list2 if val1 == val2]
будет иметь точно такой же результат.1
уже есть1
вre_list
.