当我在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]
任何人都可以学习我理解这两种不同的方式如何运作?
您需要将代码分解为更简单的形式才能理解它。以第一个例子为例。
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))
在第二个示例中,re_list在创建新列表时为空,因此val1 not in re_list
始终为false。在第一个中,您创建了re_list.append()
(None
,我记得)返回的内容列表,并在修改re_list
时将其分配给无处。
顺便问一下,为什么不使用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))
(worst case是O(len(a)*len(b))
)来做到这一点。