从列表中删除无值而不删除0值


244

这是我开始的来源。

我的清单

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值?

Answers:


353
>>> 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]

只是为了好玩,您可以filter在不使用的情况下适应这种情况lambda(我不推荐使用此代码-只是出于科学目的)

>>> 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]

23
不太优雅的filter版本: filter(lambda x: x is not None, L)-你可以摆脱的lambda使用partialoperator.is_not我想,但它可能是不值得的,因为名单-COMP是那么干净多了。
mgilson

3
@mgilson哦,我什至不知道is_not存在!我以为只是is_,我只是为了好玩而补充一下
jamylak

@jamylak-是的 实际上,这困扰着我is_not存在和not_in不存在。我实际上认为not_in应该将其转变为一种神奇的方法__not_contains__...看到我前一阵子问过的问题以及我对回答者的评论 ...仍然不觉得它已解决。
mgilson

@mgilson我认为在相同的假设下,我只是假设它不存在。我猜您可以随便使用,filterfalse还是要视情况而定
jamylak 2013年

@jamylak-是的 我的主要问题是,x > y这并不意味着not x <= ypython,因为您可以在__lt__and中进行任何操作__le__,所以为什么要x not in y暗示not x in y(尤其是因为not in它拥有自己的字节码?)
mgilson 2013年

136

FWIW,Python 3使此问题变得容易:

>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> list(filter(None.__ne__, L))
[0, 23, 234, 89, 0, 35, 9]

在Python 2中,您将改为使用列表推导:

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

+1是否建议使用__ne__like而不是partialand ne
jamylak

1
@jamylak是的,它更快,更容易编写并且更清晰。
Raymond Hettinger

考虑使用该operator模块。
2015年

12
什么__ne__
DrMcCleod'7

11
@DrMcCleod表达x != y在内部调用x.__ne__(y)其中的NE表示“不等于”。因此,None.__ne__是一个绑定方法,当使用None以外的任何值调用该方法时,返回True。例如,使用with 返回NotImplemented作为真实值,并返回Falsebm = None.__ne__bm(10)bm(None)
Raymond Hettinger

16

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

想知道在Python(和其他OO语言)中是否普遍存在“不是None”的东西,以至于在我的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模块,在这种情况下无需自定义函数
jamylak 18-2-17

16

使用列表理解可以做到以下几点:

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

l的值是:

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

最佳答案中已经找到了该解决方案,还是我错过了什么?
Qaswed

12

@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

1
@jamylak-我确实读过它,但是您没有包含此解决方案。-还不确定为什么要编辑4-5年前的人们的答案。
AT

5

迭代空间,使用可能是一个问题。在不同情况下,分析可能会显示“更快”和/或“更少的内存”密集型。

# 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, ...]

一种方法(也由@jamylak@Raymond Hettinger@Dipto提出)在内存中创建了一个重复列表,这对于只有很少None条目的大列表来说可能是昂贵的。

第二个方法经过列表一次,然后再次每次直至None到达。这可能会减少内存消耗,并且列表会变得越来越小。列表大小的减少可能会加快None前面很多条目的速度,但是最坏的情况是如果None后面很多条目。

并行化和就地技术是其他方法,但是每种方法在Python中都有其自身的复杂性。了解数据和运行时用例以及对程序进行性能分析是开始进行大量操作或处理大数据的地方。

在通常情况下,选择任何一种方法都可能无关紧要。它更多地成为符号的偏爱。实际上,在那些不常见的情况下,numpy或者cython可能是值得尝试的替代方法,而不是尝试对Python优化进行微管理。


完全不喜欢这样做,您使用此解决方案声称的全部优点是列表可能非常庞大,以至于在内存中构建重复列表可能会非常昂贵。好吧,这样您的解决方案将变得更加昂贵,因为您要扫描整个列表L.count(None),然后.remove(None)多次调用,这将使O(N^2)您无法解决正在尝试解决的问题,因此应该重组数据如果占用大量内存,则转入数据库或文件。
jamylak

@jamylak是的,但并非所有现实情况或数据都允许这种灵活性。例如,在没有太多内存的系统上通过一次性分析来泵送“遗留”地理空间数据。然后还要考虑编程时间与运行时间。由于节省了开发时间,人们经常转向Python。有了这个答案,我引起了人们注意记忆可能值得考虑的事实,但是我最后指出,记忆主要是符号的个人偏好。我还指出,了解数据很重要。O(n^2)仅当整个列表为时None
凯文(Kevin)

如果您有一个实际的例子,这个答案是最好的解决方案,我会很感兴趣,我倾向于认为在所有情况下都有更好的方法。例如numpy,能够以更优化的方式处理此类操作
jamylak '18

@jamylak公平地说,我numpy最近几年一直在使用,但这是一项单独的技能。如果L将其实例化为numpy.arrayPython而不是Python list,那么L = L[L != numpy.array(None)](stackoverflow.com/a/25255015/3003133)可能比任何一个都要好,但是我不知道下面处理与内存的实现细节。它至少会为掩码创建一个重复的布尔长度数组。这样,访问(索引)运算符内部比较的语法对我来说是新的。这个讨论也引起了我的注意dtype=object
凯文(Kevin)

现在,讨论变得太抽象了,我认为您无法在我多年的经验中给我一个真实的例子,在这个例子中,正如我之前提到的,此答案是重构数据的正确方法。
jamylak

2
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))

6
请为OP提供一些详细信息,而不仅仅是代码。
洛朗·拉波特

1
是的 你认为呢?
med_abidi '16

好吧,这不能回答OP问题。请考虑以下答案:stackoverflow.com/a/16096769/1513933
劳伦·劳波特

是的,你是对的。过滤器部分存在问题。
med_abidi '16

2

如果全部是列表列表,则可以修改@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]"""

<<如果变量不是None,则List中变量的list_indice [0] >>


1

说列表如下

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, {}, (), []]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.