首页 > 解决方案 > 我想创建一个函数,它接受一个列表并返回相同的列表但没有重复的元素,这个程序有什么问题?

问题描述

我想做一个函数,它接受一个列表并返回相同的列表但没有重复的元素

def func(list1):
    for i in range(len(list1)):
        list2 = [x for x in list1 if x != list1[i]]
        if list1[i] in list2:
            list1.remove(i)
            return list1
        

mylist = [1,2,3,4]
func(mylist)

标签: pythonlistfunction

解决方案


已经有很多答案展示了如何正确实现此任务,但没有一个讨论您的实际代码。

解构你的代码

希望这将有助于理解为什么您的代码不起作用。这是您的代码,添加了注释:

def func(list1):
    for i in range(len(list1)):
        list2 = [x for x in list1 if x != list1[i]]

在这里,您构造了一个list2不包含的列表list1[i]

        if list1[i] in list2:

这个if陈述总是错误的,由list2.

            list1.remove(i)

即使您修复了if语句的逻辑,list1.remove(i)也会造成麻烦:尝试在迭代列表时删除列表的元素会使其余迭代的索引无效。最好避免这样做,而是将结果构建到一个新列表中。

此外,它正在list1.remove(i)寻找价值并将其删除,无论它首先找到它。正如这段代码所期望的那样,它没有删除第 i 个元素。ilist1

            return list1

而这个返回语句可能并不意味着缩进这么深,它应该可能for与顶部的语句处于同一水平。

工作代码更接近你的逻辑

虽然我认为这不是最好的解决方案——其他答案提供了更好的解决方案——但这是一个受您的代码启发的解决方案,它有效。

def func(list1):
    list2 = []  # We'll append elements here
    for item in list1:  # more pythonic way to loop over a list
        if item not in list2:
            list2.append(item)
    return list2

我的首选解决方案

好的,所以现在我在其他答案中复制信息,但是使用 Python 3.7(*) 或更新版本,dict保证插入其中的元素的顺序保持不变,我会使用@Pedro Maia 的解决方案:

def func(list1):
    return list(dict.fromkeys(list1))

事实上,我最近在我的代码库中使用了这种技术。

在旧版本的 Python 中,dicts 没有排序。但是,自 Python 2.7 以来OrderedDict,该库中一直存在该类collections,因此此代码适用于任何版本的 Python >= 2.7:

from collections import OrderedDict
def func(list1):
    return list(OrderedDict.fromkeys(list1))

如果您不熟悉它们,请查看collectionslibraryitertoolslibrary,它们为各种问题提供了非常有用的帮助。

(*) 根据手册collections.OrderedDict,Pythondict只保证从 Python 3.7 开始订购,即使它们实际上是在 Python 3.6 中开始订购的,至少对于 CPython 实现是这样。另请参阅: 字典是否在 Python 3.6+ 中排序?


推荐阅读