【问题标题】:Why does removing duplicates from a list produce [None, None] output?为什么从列表中删除重复项会产生 [None, None] 输出?
【发布时间】:2015-09-19 04:26:18
【问题描述】:

我是 Python 新手,我无法理解为什么我会得到带有 None 值的结果。

#Remove duplicate items from a list
def remove_duplicates(list):
    unique_list = []
    return [unique_list.append(item) for item in list if item not in unique_list]
print remove_duplicates([1,1,2,2]) -> result [None, None]

当我打印结果时,它显示如下:[None, None]

PS:我见过其他解决方案,也知道 list(set(list)) 但我试图理解为什么上面的整数结果会给出 [None, None] 输出。

【问题讨论】:

  • 不是更容易吗:return list(set(list)) ?
  • 因为您的语句返回一个列表,其返回值为unique_list.append(item),即None
  • 顺便说一句,不要不要使用list作为变量名,它是builtin function
  • 谢谢您的所有回答

标签: python


【解决方案1】:

尽管使用了set is the proper way,但正如 cmets 所指出的,您的代码的问题在于您实际上并未从函数中返回 unique_list,而是返回了列表推导的结果。

def remove_duplicates(my_list):
    unique_list = []
    do = [unique_list.append(item) for item in my_list if item not in unique_list]
    return unique_list  # Actually return the list!

print remove_duplicates([1,1,2,2]) -> result [1, 2]

在这里,我只是简单地创建了一个无用的一次性变量do,它只是“运行”理解。明白吗?

每次调用unique_list.append(item) 时,该理解都会存储一个值...而该值是append 方法的结果,即None!所以do 等于[None, None]

但是,您的 unique_list 实际上已正确填充,因此我们可以返回它,现在您的函数按预期工作。

当然,这不是列表推导的正常用法,而且很奇怪。

【讨论】:

  • 您是否有理由对未使用的变量 do 进行赋值?
  • 目标是明确该变量是无用的,而不是所需的输出。我想暗示该语句正在“执行”,但没有使用结果。
  • 我不确定我是否应该为他没有返回 unique_list 的好消息投票赞成这个答案,或者因为你对 do 犯的一个糟糕的错误而投票反对(这真的没有必要,理解也将在没有分配的情况下运行)。
  • 嗯,问题是“为什么函数返回 [None, None]”,所以......很难说。 ;) 我将添加一个指向集合文档的链接。
  • 如果你真的想在里面放一个变量,你可以写_ = […]
【解决方案2】:

您的代码的问题是方法list.append 返回无。您可以使用以下代码轻松测试:

myList=[1, 2, 3]
print myList.append(4)

因此,您会遇到的解决方案是

def remove_duplicates(myList):
    alreadyIncluded = []
    return [item for item in myList if item not in alreadyIncluded and not alreadyIncluded.append(item)]
print remove_duplicates([1,1,2,2]) 

我们的想法是,您将从一个已包含元素的空列表开始,然后您将遍历列表中的所有元素,包括alreadyIncluded 列表中的它们。 not 是必需的,因为 append 将返回 None 并且 not NoneTrue,因此 if 不会受到包含的影响。

您包含了附加结果的列表(始终为None),但您需要的是通过if 测试的元素列表。

希望对你有帮助。

【讨论】:

  • 谢谢 rLinden 的解释。
【解决方案3】:

正如其他答案所解释的那样,您获得None 值列表的原因是因为list.append 返回None,并且您在列表理解中调用它。这意味着您正在构建一个包含 None 值的列表以及您的唯一值列表。

我想建议你放弃列表理解。因为您需要访问外部状态(到目前为止看到的唯一值列表),所以理解不能轻易地做您想做的事。常规的for 循环更合适:

def remove_duplicates(lst):
    unique_list = []
    for item in lst:
        if item not in unique_list:
            unique_list.append(item)
    return unique_list

然而,更 Pythonic 的方法是使用 set 来处理唯一项,并使您的函数成为生成器:

def remove_duplicates(lst):
    uniques = set()
    for item in lst:
        if item not in unique_list:
            yield item
            uniques.add(item)

标准库中的itertools.ifilterfase 函数可以帮助进一步改进这一点,如recipe in the docs 所示(您必须向下滚动一点才能找到具体的配方):

def unique_everseen(iterable, key=None):
    "List unique elements, preserving order. Remember all elements ever seen."
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
    # unique_everseen('ABBCcAD', str.lower) --> A B C D
    seen = set()
    seen_add = seen.add
    if key is None:
        for element in filterfalse(seen.__contains__, iterable):
            seen_add(element)
            yield element
    else:
        for element in iterable:
            k = key(element)
            if k not in seen:
                seen_add(k)
                yield element

【讨论】:

  • 谢谢 BlckKnght 提供不同的解决方案。
猜你喜欢
  • 1970-01-01
  • 2013-08-14
  • 2016-12-15
  • 2015-01-14
  • 1970-01-01
  • 2022-11-27
  • 1970-01-01
相关资源
最近更新 更多