本文共 2833 字,大约阅读时间需要 9 分钟。
我希望使用此结构来延迟列表中的重复元素,但使用此代码时列表保持不变。有人能帮我吗?
例如,item=[1,2,3,4,5,6,7,8,9,1,2,6,7]
def duplicated(item):
i=0
j=0
while i
while j
if item[j]==item[i] and i!=j:
del item[j]
j+=1
i+=1
return item
没有重复。一些数字会被删除;在函数之后肯定不会改变。你在问它为什么不删除所有的重复项吗?
是的,对不起,我在问为什么它没有把所有的副本都延迟。
尝试运行它,例如pythontutor.com/visualize.html mode=edit-有些会被删除,但您的逻辑是错误的,所以并不是所有对都进行比较。
迭代时如何从列表中删除项的可能重复项?或者正如我(删除的)回答中所提到的:如何从列表中删除重复项同时保留
您在迭代列表时正在修改它。看看那个混蛋为什么不行。
@Patrickartner说,我不介意一个解释为什么OP的代码不起作用的答案。如果你链接到一个现有的问题而不是(重新)发布现有的解决方案,我更愿意。
循环中如何从python列表中删除项的可能重复项?
为了解决代码不工作的原因,这是因为您在函数开始时初始化了j,所以在i循环的第一次迭代之后,它是len(item)-1,然后再也不会为将来的循环重置。
这意味着你错过了许多副本。
所以,既然我们需要在每个循环中初始化它,我们仍然需要知道该怎么做。如果我们将其初始化为0,那么我们将检查列表中当前j值后面的重复项,这样做是浪费时间。为了提高效率,我们应该将其初始化为i+1,以便我们检查i后面的数字是否有重复项,因为我们已经知道列表中索引i之前i处的值没有重复项。这也简化了if,因为我们不再需要检查i != j。
最后一件事是,当使用del删除j时,后面的所有索引现在都向下移动了一个。因此,我们还需要从j中减去1,这样我们就可以直接检查刚刚删除的元素之后的元素,它现在与刚刚删除的元素索引相同(因为它们被下移)。
所以,在代码中:
def duplicated(item):
i = 0
while i < len(item):
j = i + 1
while j < len(item):
if item[j] == item[i]:
del item[j]
j -= 1
j += 1
i += 1
return item
它与人们给出的例子一起工作:
>>> duplicated([1,2,3,4,5,6,7,8,9,1,2,6,7])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> duplicated([1,2,3,4,5,6,7,8,9,1,1,2,6,7])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
。
但是,由于我们使用的是嵌套循环,所以所用的时间与输入列表的平方大小成正比,因此该解决方案是目前的O(n^2)复杂性解决方案。
但是,如果我们能够将算法修改为只使用一个循环,我们将把复杂性降低到O(n)。这可以通过使用查找集来完成。添加和检查集合中的元素是否是EDOCX1(平均大小写21),这样我们就可以使用它们来加快速度。
因此,如果我们有一个集合包含我们已经看到的元素,那么对于每个未来的元素,如果它已经在seen集合中,我们删除它,否则我们将它添加到这个集合中。
所以,在代码中:
def duplicated(item):
seen = set()
i = 0
while i < len(item):
if item[i] in seen:
del item[i]
else:
seen.add(item[i])
i += 1
return item
我可以确认这也通过了上面的测试用例。
我要指出的最后一点是,在这里删除元素时,我没有从指针中减去,这是因为在我们减去之前,我们知道它稍后会增加,我们希望它是相同的,但是在这里,它只在else块中增加,所以如果我们不做任何事情,它将保持不变。
这里可以找到其他解决方案。
实际上,变量j应该从i选择的下一项开始。
def duplicated(item):
i=0
while i
j = i+1
while j
if item[j]==item[i] and i!=j:
del item[j]
j -= 1
j+=1
i+=1
return item
。
每次嵌套while循环开始时需要重新初始化j:
def duplicated(item):
i=0
j=0
while i
j=i+1
while j
if item[j]==item[i]:
del item[j]
j -= 1
j+=1
i+=1
return item
。出
[1, 2, 3, 4, 5, 6, 7, 8, 9]
。
但是,您可以尝试以下更简单的代码,它将保持列表的插入顺序
def duplicated(item):
unique_list=[]
for i in item:
if i not in unique_list:
unique_list.append(i)
return unique_list
这会对输入[1,2,1,1]引发索引错误。另外,第二个解决方案是可怕的,因为它是O(n^2)。请链接到现有问题以获得解决方案,而不是发布自己的(坏)解决方案。
@阿兰·费伊,对新手来说应该很好,因为他们首先应该专注于工作,然后才能专注于效率。
@Aran Fey使用一个for循环,它将是O(n^2)
if i not in unique_list
@aran fey您所指的问题明确要求效率时间,但这个问题需要代码来工作,并且他使用的while循环代码比我建议的备用代码更复杂。
你应该在i循环的每一圈重新初始化你的jvar,否则,在第一次迭代之后,j总是等于len(item)。
def duplicated(item):
i=0
while i
j=0
while j
if item[j]==item[i] and i!=j:
print(i,j )
del item[j]
j+=1
i+=1
return item
但是,如果不关心列表顺序,最好的方法可能是将列表转换为一个集合,然后再转换回一个列表,有一个集合只能有不同的元素。
def duplicated(item):
return list(set(item))
号
警告:集合无序
您还可以使用i+1初始化j,并节省一些周期。
代码仍然有错误。它对输入[1,2,3,4,5,6,7,8,9,1,1,2,6,7]抛出一个索引错误。
list(OrderedDict([(i, None) for i in item]).keys())保留订单
转载地址:http://dxdoo.baihongyu.com/