【问题标题】:Why I get the list unchanged when using this code?为什么在使用此代码时列表不变?
【发布时间】:2018-10-01 21:13:15
【问题描述】:

我想使用此结构删除列表中的重复元素,但当我使用此代码时列表保持不变。谁能帮帮我?

例如,item=[1,2,3,4,5,6,7,8,9,1,2,6,7]

def duplicated(item):
        i=0
        j=0
        while i<len(item):
                while j<len(item):
                        if item[j]==item[i] and i!=j:
                                del item[j]
                        j+=1
                i+=1
        return item

【问题讨论】:

标签: python


【解决方案1】:

要解决您的代码不工作的原因,这是由于您在函数开始时初始化了j,因此在i 循环的第一次迭代之后,它是len(item)-1 和然后永远不要为将来的循环重置。

这意味着你错过了很多重复。

因此,由于我们需要在每个循环中初始化它,我们仍然需要知道要做什么。如果我们将其初始化为0,那么我们正在检查列表中当前j 值后面的重复项,所以这是浪费时间。为了提高效率,我们应该将其初始化为 i+1 以便我们检查数字 after i 是否有重复,因为我们已经知道在索引 @ 之前 i 的值没有重复987654330@ 在列表中。这也简化了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)。这可以通过使用一组查找来完成。添加并检查一个元素是否在集合中是O(1)(平均情况),因此我们可以使用它们来加快速度。

因此,如果我们有一个包含我们已经看到的元素的集合,那么对于每个未来的元素,如果它已经在 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 块中递增,所以如果我们什么都不做,它会保持不变。

【讨论】:

  • 可以在here找到替代解决方案。
【解决方案2】:

实际上变量j 应该从i 选择的下一项开始。

def duplicated(item):
    i=0
    while i<len(item):
        j = i+1
        while j<len(item):
            if item[j]==item[i] and i!=j:
                del item[j]
                j -= 1
            j+=1
        i+=1
    return item

【讨论】:

    【解决方案3】:

    您应该在 i 循环内的每一轮重新初始化您的 j 变量,否则,在第一次迭代之后,j 将始终等于 len(item)

    def duplicated(item):
        i=0
        while i<len(item):
            j=0
            while j<len(item):
                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并节省一些周期
    • 代码还是有bug。它使用输入 [1,2,3,4,5,6,7,8,9,1,1,2,6,7] 引发 IndexError。
    • list(OrderedDict([(i, None) for i in item]).keys()) 保留订单
    【解决方案4】:

    你需要在每次嵌套while循环开始时重新初始化j:

    def duplicated(item):
            i=0
            j=0
            while i<len(item)-1:
                j=i+1
                while j<len(item):
                        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
    

    【讨论】:

    • 这会引发 IndexError 输入为[1,2,1,1]。此外,第二个解决方案很糟糕,因为它是 O(n^2)。请链接到an existing question 以获得解决方案,而不是发布您自己的(错误的)解决方案。
    • @Aran-Fey 新手应该没问题,首先他们应该专注于工作解决方案,然后才能专注于效率
    • @Aran-Fey 使用一个 for 循环将如何 O(n^2)
    • if i not in unique_list
    • @Aran-Fey 你提到的问题他明确询问效率时间,但这个问题需要代码才能工作,而且他使用 while 循环使用的代码比我建议的替代代码更复杂
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    • 2011-09-30
    • 2013-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多