Python:如何从列表中删除空列表?

101
我有一个包含空列表的列表:
list1 = [[], [], [], [], [], 'text', 'text2', [], 'moreText']

我该如何移除空列表,以便得到:

list2 = ['text', 'text2', 'moreText']

我尝试使用list.remove(''),但那并没有起作用。


4
“'' != []”这个条件是成立的,所以.remove方法无法正常工作。但这仍然不是一个好的解决方案(要么你事先检查列表中是否存在[] - O(n ** 2) - 要么捕捉它抛出的错误 - 很丑陋)。 - user395760
1
太神奇了,当你发现虽然你的问题不常见,但是早先有人已经发布了它,并且已经得到了精美的回答!我爱 Stack Overflow。 - Sibbs Gambling
9个回答

170
尝试
list2 = [x for x in list1 if x != []]

如果你想要摆脱所有的“假值”,例如空字符串、空元组和零, 你也可以使用:

list2 = [x for x in list1 if x]

5
+1 是因为提及了另一种方式以及它与之前的方法有所不同。 - user395760
我知道这很老,但我一直看到那个大括号的方法,但我在谷歌上找不到任何相关信息(可能是因为谷歌不会处理标点符号)。那叫什么名字,这样我就可以了解更多关于那里真正发生了什么? - David
5
List comprehensionsGenerator expressions 是Python中一种简洁的语法,用于快速创建列表和生成器。此外,还有字典推导式和集合推导式。 - Sven Marnach

90

你可以使用filter()而不是列表推导来实现:

list2 = filter(None, list1)

如果在filter()的第一个参数中使用None,它将过滤掉给定列表中在布尔上下文中为False的每个值,包括空列表。
这可能比列表推导略微快一些,因为它只在Python中执行单个函数,其余部分在C中完成。

1
为什么这个答案没有更多的赞和/或成为被采纳的答案? - tumultous_rooster
5
许多Python程序员避免使用 filter(),以及 lambdamap()reduce()函数; 这包括 Guido 本人,尽管该文章有点老。我倾向于使用列表推导式,因为清晰度通常比这些方法和 lambda 运算符的轻微加速更重要。话虽如此,这个例子很简单,因为程序员的意图非常明确。 - BoltzmannBrain
21
在Python3中,我认为这需要修改为:list2 = list(filter(None, list1))。以防任何使用Python3的新手想知道为什么这对他们不起作用 :) - Shaken_not_stirred.
@Shaken_not_stirred。没错!我是个新手,我喜欢 Stack Overflow。这个回答帮助我避免了数小时的抓狂! - Tonya Howe

10

使用filter函数参数传入None,将会从列表中过滤掉所有假值(包括空列表)。

list2 = filter(None, list1)

7
>>> list1 = [[], [], [], [], [], 'text', 'text2', [], 'moreText']
>>> list2 = [e for e in list1 if e]
>>> list2
['text', 'text2', 'moreText']

1
有人可以帮我编辑一下吗?我似乎无法获得格式选项。 - user225312
完成 - user180100
@RC:谢谢!我知道,但出于某种奇怪的原因它不可见(没有选项)。 - user225312

4
一些选项:
filter(lambda x: len(x) > 0, list1)  # Doesn't work with number types
filter(None, list1)  # Filters out int(0)
filter(lambda x: x==0 or x, list1) # Retains int(0)

示例会话:

Python 2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> list1 = [[], [], [], [], [], 'text', 'text2', [], 'moreText']
>>> filter(lambda x: len(x) > 0, list1)
['text', 'text2', 'moreText']
>>> list2 = [[], [], [], [], [], 'text', 'text2', [], 'moreText', 0.5, 1, -1, 0]
>>> filter(lambda x: x==0 or x, list2)
['text', 'text2', 'moreText', 0.5, 1, -1, 0]
>>> filter(None, list2)
['text', 'text2', 'moreText', 0.5, 1, -1]
>>>

"-1: len(x) > 0 实际上与 bool(x) 或仅仅是 x 是相同的。" - user355252
+1:@RC。如果您的列表中有数字类型,就不能对其调用len。如果您有一个0,它将被None过滤掉。否则我喜欢这个答案。 - Bruno Bronosky

2

我发现这个问题是因为我想要和OP一样做。 我想要补充以下观察:

迭代方式(user225312,Sven Marnach):

list2 = [x for x in list1 if x]

将返回一个python3python2中的list对象。而过滤方式(lunaryorn,Imran)在不同版本中的行为也会有所不同:

list2 = filter(None, list1)

它将返回一个python3中的filter对象和python2中的list(同时参见this question)。这是一个细微的差别,但在开发兼容脚本时必须考虑到。

这不会对这些解决方案的性能做出任何假设。无论如何,可以使用以下方法将过滤器对象还原为列表:

list3 = list(list2)

1
list1 = [[], [], [], [], [], 'text', 'text2', [], 'moreText']
list2 = []
for item in list1:
    if item!=[]:
        list2.append(item)
print(list2)

输出:

['text', 'text2', 'moreText']

1
仅仅给出代码并不是很有用。如果您能添加一些详细的解释说明它是如何回答这个问题的,那将会更有帮助。话虽如此,我不确定这个答案是否比其他所有五年前的答案都更有价值。 - SiHa

1
a = [[1,'aa',3,12,'a','b','c','s'],[],[],[1,'aa',7,80,'d','g','f',''],[9,None,11,12,13,14,15,'k']]

b=[]
for lng in range(len(a)):
       if(len(a[lng])>=1):b.append(a[lng])
a=b
print(a)

输出:

[[1,'aa',3,12,'a','b','c','s'],[1,'aa',7,80,'d','g','f',''],[9,None,11,12,13,14,15,'k']]

你在2015年发布了这个帖子,直到2021年解决了我的问题才得到了零分。教训是:继续提供帮助。你不知道谁会从你的解决方案中受益最多!谢谢。加一。 - Omojola Micheal

0

在上面的回答中添加,假设你有一个形如列表的列表

theList = [['a','b',' '],[''],[''],['d','e','f','g'],['']]

如果您想从每个列表中删除空条目以及空列表,可以执行以下操作:

theList = [x for x in theList if x != ['']] #remove empty lists
for i in range(len(theList)):
    theList[i] = list(filter(None, theList[i])) #remove empty entries from the lists

你的新列表将会是这样的

theList = [['a','b'],['d','e','f','g']]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接