追加和为列表分配值有什么区别?

问题描述 投票:1回答:3

当我在Python中使用one-line-for循环时,根据我选择的进程(分配和追加进程),我将得到两个不同的值。我想了解它们的区别以及它们的工作原理。在以下两个示例中,我尝试编写一个程序,该程序返回一个列表,该列表仅包含列表之间通用的元素(没有重复项)。

第一个附加程序,我得到了正确的结果:

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]

任何人都可以学习我理解这两种不同的方式如何运作?

python python-3.x for-loop
3个回答
3
投票

您需要将代码分解为更简单的形式才能理解它。以第一个例子为例。

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在创建生成器时为空。

最后来到你的解决方案:

我试图编写一个程序,返回一个列表,该列表只包含列表之间通用的元素(没有重复)。

您应该遵循Jon Clements♦建议并使用集合实现它

你应该看看集合......例如:list(set(a).intersection(b))


2
投票

在第二个示例中,re_list在创建新列表时为空,因此val1 not in re_list始终为false。在第一个中,您创建了re_list.append()None,我记得)返回的内容列表,并在修改re_list时将其分配给无处。

顺便问一下,为什么不使用set()获取一系列独特元素?


1
投票
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))worst caseO(len(a)*len(b)))来做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.