【问题标题】:remove None value from a list without removing the 0 value从列表中删除 None 值而不删除 0 值
【发布时间】:2013-04-12 09:10:53
【问题描述】:

This was my source I started with.

我的清单

L = [0, 23, 234, 89, None, 0, 35, 9]

当我运行这个时:

L = filter(None, L)

我得到了这个结果

[23, 234, 89, 35, 9]

但这不是我需要的,我真正需要的是:

[0, 23, 234, 89, 0, 35, 9]

因为我正在计算数据的百分位数,而 0 有很大的不同。

如何在不删除 0 值的情况下从列表中删除 None 值?

【问题讨论】:

    标签: python list filter list-comprehension nonetype


    【解决方案1】:
    >>> L = [0, 23, 234, 89, None, 0, 35, 9]
    >>> [x for x in L if x is not None]
    [0, 23, 234, 89, 0, 35, 9]
    

    只是为了好玩,以下是您如何在不使用 lambda 的情况下调整 filter 来执行此操作,(我不推荐此代码 - 仅用于科学目的)

    >>> from operator import is_not
    >>> from functools import partial
    >>> L = [0, 23, 234, 89, None, 0, 35, 9]
    >>> filter(partial(is_not, None), L)
    [0, 23, 234, 89, 0, 35, 9]
    

    【讨论】:

    • 不太优雅的filter 版本:filter(lambda x: x is not None, L) -- 你可以使用partialoperator.is_not 摆脱lambda 我认为,但它可能不值得,因为列表-comp 干净多了。
    • @mgilson 哇哦,我什至不知道is_not 存在!我以为只是is_,我只是为了好玩而添加它
    • @jamylak -- 是的。 is_not 存在而 not_in 不存在实际上让我感到困扰。我实际上认为not_in 应该变成一种神奇的方法__not_contains__ ...看到question我前一段时间问了一个comment我给一个回答者...但仍然不喜欢解决了。​​
    • @mgilson 我认为在同样的假设下,我只是假设它不存在。我想你可以根据用例使用filterfalse 或其他东西
    • @jamylak -- 是的。我的主要问题是x > y在python中并不暗示not x <= y,因为你可以在__lt____le__中做任何事情,那么x not in y为什么要暗示not x in y(尤其是因为not in有它自己的字节码?)
    【解决方案2】:

    使用列表推导可以如下完成:

    l = [i for i in my_list if i is not None]
    

    l的值为:

    [0, 23, 234, 89, 0, 35, 9]
    

    【讨论】:

    • 此解决方案已在最佳答案中找到,还是我遗漏了什么?
    【解决方案3】:

    list comprehension 可能是最干净的方式:

    >>> L = [0, 23, 234, 89, None, 0, 35, 9
    >>> [x for x in L if x is not None]
    [0, 23, 234, 89, 0, 35, 9]
    

    还有一种functional programming 方法,但涉及更多:

    >>> from operator import is_not
    >>> from functools import partial
    >>> L = [0, 23, 234, 89, None, 0, 35, 9]
    >>> list(filter(partial(is_not, None), L))
    [0, 23, 234, 89, 0, 35, 9]
    

    【讨论】:

    • @jamylak 是的,它更快,更容易编写,更清晰。
    • 考虑使用operator 模块。
    • 什么是__ne__
    • @DrMcCleod 表达式x != y 在内部调用x.__ne__(y),其中ne 代表“不等于”。因此,None.__ne__ 是一个绑定方法,当使用 None 以外的任何值调用时,它会返回 True。例如,bm = None.__ne__bm(10) 一起调用返回 NotImplemented 作为真值,bm(None) 返回 False
    • NotImplemented 在布尔上下文中为真真的很奇怪。请参阅Make NotImplemented unusable in boolean context Python 问题。
    【解决方案4】:

    对于 Python 2.7(请参阅 Raymond 的回答,对于 Python 3 等效版本):

    想知道“不是无”在 python(和其他 OO 语言)中是否如此常见,以至于在我的 Common.py(我使用“from Common import *”导入每个模块)中,我包括了这些行:

    def exists(it):
        return (it is not None)
    

    然后要从列表中删除 None 元素,只需执行以下操作:

    filter(exists, L)
    

    我发现这比相应的列表理解(Raymond 展示的 Python 2 版本)更容易阅读。

    【讨论】:

    • 我更喜欢 Python 3 的 Raymonds 解决方案,然后是 Python 2 的列表推导式。但如果我必须走这条路,我宁愿 partial(is_not, None) 也不要这个解决方案。我相信这会更慢(尽管那不是太重要)。但是有了几个 python 模块的导入,在这种情况下不需要自定义函数
    • 自定义函数不仅仅适用于这种情况。如果是,我就不会定义一个函数!我是说我发现在很多情况下说“如果存在(某物)”而不是说“如果某物不是无”更易读。它更接近我的想法,并且避免了说“不是无”的“双重否定”。
    • 我明白你的意思是避免双重否定,实际上在exists 的定义中return (it is not None) 是一种明确的定义方式。 (也许我会删除括号,但这只是一件小事)
    【解决方案5】:

    @jamylak 的回答非常好,但是如果您不想为了完成这个简单的任务而导入几个模块,请在原地编写自己的 lambda

    >>> L = [0, 23, 234, 89, None, 0, 35, 9]
    >>> filter(lambda v: v is not None, L)
    [0, 23, 234, 89, 0, 35, 9]
    

    【讨论】:

    • 你显然没有正确阅读我的解决方案 [x for x in L if x is not None] 其他代码只是我明确表示我不会推荐的补充
    • @jamylak - 我确实读过它,但你没有包括这个解决方案。 - 也不知道你为什么要编辑 4-5 年前人们的答案。
    【解决方案6】:

    Iteration vs Space,使用可能是个问题。在不同的情况下,分析可能会显示为“更快”和/或“更少内存”密集型。

    # first
    >>> L = [0, 23, 234, 89, None, 0, 35, 9, ...]
    >>> [x for x in L if x is not None]
    [0, 23, 234, 89, 0, 35, 9, ...]
    
    # second
    >>> L = [0, 23, 234, 89, None, 0, 35, 9]
    >>> for i in range(L.count(None)): L.remove(None)
    [0, 23, 234, 89, 0, 35, 9, ...]
    

    first 方法(也由@jamylak@Raymond Hettinger@Dipto 建议)在内存中创建一个重复列表,这对于包含很少内容的大型列表可能会占用大量内存None 条目。

    second 方法遍历列表一次,然后每次都遍历一次,直到到达None。这可能会占用更少的内存,并且列表会随着时间的推移而变得更小。列表大小的减少可能会加快前面的大量 None 条目,但最坏的情况是如果后面有大量 None 条目。

    第二种方法可能总是比第一种方法慢。这并不意味着它是一个无效的考虑。

    并行化和就地技术是其他方法,但它们在 Python 中都有各自的复杂性。了解数据和运行时用例以及分析程序是密集操作或大数据的起点。

    在常见情况下,选择任何一种方法都可能无关紧要。它变得更像是一种符号偏好。事实上,在那些不常见的情况下,numpy(例如,如果 L 是 numpy.array:L = L[L != numpy.array(None) (from here))或cython 可能是值得的替代方案,而不是尝试对 Python 优化进行微观管理。

    【讨论】:

    • 根本不喜欢这个,您声称使用此解决方案的全部优势是列表可能如此庞大以至于在内存中构建重复列表可能会很昂贵。那么您的解决方案将成本更高,因为您正在扫描整个列表以查找L.count(None),然后您多次调用.remove(None),这使得O(N^2)成为您正在尝试的情况要解决的问题不应该以这种方式处理,如果它是内存密集型的,则应将数据重组为数据库或文件。
    • 如果你有一个实际例子,这个答案是最好的解决方案,我会很感兴趣,我倾向于认为在所有情况下都会有更好的方法。例如numpy 将能够以更优化的方式处理此类操作
    • 这个讨论现在变得太抽象了,我认为您无法在您多年的经验中给我一个真实的例子,这个答案是重组数据的正确方法我之前提到过。
    • 没错,但并非所有现实世界的情况都允许灵活地转换数据。例如,通过对没有太多内存的系统进行一次性分析来抽取“遗留”地理空间数据。另一个例子是编程时间与运行时间。可能不在乎某些东西是否需要整晚才能运行,只要它的编写成本不高。如果编写插件或库怎么办?您可能不是决定数据是什么样子的人。有了这个答案,我将注意力集中在考虑内存和了解数据上,但我指出这在大多数情况下可能并不重要。
    • 最好的情况是O(n)。数 n 却一无所获。所有None 将是O(2n)。计数 == n 个操作;然后在第一项上找到每个删除比较,因此总比较为 n。列表末尾的单个 None 也是 O(2n)。计数为 n;再通过列表一次,直到在最后一个位置 n 中找到 None。所以,我认为最坏的情况是列表的后半部分完全没有。我认为那是O(n + ((n / 2) + 1)^2)。另一个现实世界的场景是具有少量内存的嵌入式系统。 Micropython 专门为这些而存在。
    【解决方案7】:
    from operator import is_not
    from functools import partial   
    
    filter_null = partial(filter, partial(is_not, None))
    
    # A test case
    L = [1, None, 2, None, 3]
    L = list(filter_null(L))
    

    【讨论】:

    • 请向 OP 提供一些详细信息,而不仅仅是代码。
    • 我做到了。你怎么看?
    • 好吧,这并不能回答 OP 问题。请考虑这个答案:stackoverflow.com/a/16096769/1513933
    • 是的,你是对的。部分过滤器出现问题。
    【解决方案8】:

    说列表如下所示

    iterator = [None, 1, 2, 0, '', None, False, {}, (), []]
    

    这将只返回那些bool(item) is True的项目

    print filter(lambda item: item, iterator)
    # [1, 2]
    

    这相当于

    print [item for item in iterator if item]
    

    只过滤无:

    print filter(lambda item: item is not None, iterator)
    # [1, 2, 0, '', False, {}, (), []]
    

    相当于:

    print [item for item in iterator if item is not None]
    

    获取所有评估为 False 的项目

    print filter(lambda item: not item, iterator)
    # Will print [None, '', 0, None, False, {}, (), []]
    

    【讨论】:

      【解决方案9】:

      如果都是列表,你可以修改@Raymond先生的回答

      L = [ [None], [123], [None], [151] ] no_none_val = list(filter(None.__ne__, [x[0] for x in L] ) ) 但是对于 python 2

      no_none_val = [x[0] for x in L if x[0] is not None] """ Both returns [123, 151]"""

      >

      【讨论】:

        【解决方案10】:
        L = [0, 23, 234, 89, None, 0, 35, 9] 
        result = list(filter(lambda x: x is not None, L))
        

        【讨论】:

          【解决方案11】:

          如果列表有 NoneType 和 pandas._libs.missing.NAType 对象,则使用:

          [i for i in lst if pd.notnull(i)]
          

          【讨论】:

          • 使用熊猫是个好主意!谢谢@sedrak,欢迎来到这个平台
          猜你喜欢
          • 1970-01-01
          • 2017-10-12
          • 2022-10-25
          • 2022-06-19
          • 1970-01-01
          • 1970-01-01
          • 2021-11-09
          • 1970-01-01
          • 2022-09-29
          相关资源
          最近更新 更多