В чем разница между добавлением и назначением значения в список? - PullRequest
0 голосов
/ 30 августа 2018

Когда я использую однострочный цикл в 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]

Но когда я использую метод assign как следующий, я получу неправильный ответ:

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]

Любой может научить меня понимать, как работают эти два разных способа?

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

Вам нужно разбить код на более простую форму, чтобы понять его. Взять первый пример.

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)

OUTPUT

[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 пусто при создании генератора.

Наконец-то пришло ваше решение:

Я пытаюсь написать программу, которая возвращает список, который содержит только элементы, общие для списков (без дубликатов).

Вы должны следовать совету Джона Клементса и выполнять его, используя набор

Вы должны взглянуть на наборы ... например: список (набор (а). Пересечение (б))

0 голосов
/ 30 августа 2018
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))).

0 голосов
/ 30 августа 2018

Во втором примере re_list пуст к моменту создания нового списка, поэтому val1 not in re_list всегда ложно. В первом вы создаете список того, что возвращает re_list.append() (None, насколько я помню), и назначаете его в никуда при изменении re_list.

Кстати, почему бы вам не использовать set() для получения списка уникальных элементов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...