从字符串列表中删除空字符串

我想从python中的字符串列表中删除所有空字符串。

我的想法看起来像这样:

while '' in str_list:str_list.remove('')

有没有其他的Pythonic方法来做到这一点?

1007729 次浏览

使用列表理解是最Pythonic的方式:

>>> strings = ["first", "", "second"]>>> [x for x in strings if x]['first', 'second']

如果必须就地修改列表,因为还有其他引用必须看到更新的数据,那么使用切片赋值:

strings[:] = [x for x in strings if x]

我会使用filter

str_list = filter(None, str_list)str_list = filter(bool, str_list)str_list = filter(len, str_list)str_list = filter(lambda item: item, str_list)

Python 3从filter返回一个迭代器,因此应该包装在对list()的调用中

str_list = list(filter(None, str_list))

根据列表的大小,使用list.remove()而不是创建一个新列表可能是最有效的:

l = ["1", "", "3", ""]
while True:try:l.remove("")except ValueError:break

这具有不创建新列表的优点,但缺点是每次都必须从头开始搜索,尽管与上面提出的使用while '' in l不同,它只需要每次出现''搜索一次(当然有一种方法可以保持两种方法的最佳效果,但它更复杂)。

过滤器实际上有一个特殊的选项:

filter(None, sequence)

它将过滤掉所有计算为False的元素。这里不需要使用实际的可调用对象,例如bool、len等。

它和map一样快(bool,…)

使用filter

newlist=filter(lambda x: len(x)>0, oldlist)

使用过滤器的缺点是它比替代品慢;此外,lambda通常是昂贵的。

或者你可以选择最简单和最迭代的:

# I am assuming listtext is the original list containing (possibly) empty itemsfor item in listtext:if item:newlist.append(str(item))# You can remove str() based on the content of your original list

这是最直观的方法,并在适当的时间内完成。

而不是if x,我会使用if X ! = '' 来消除空字符串。像这样:

str_list = [x for x in str_list if x != '']

这将在您的列表中保留无数据类型。此外,如果您的列表有整数并且0是其中之一,它也将被保留。

例如,

str_list = [None, '', 0, "Hi", '', "Hello"][x for x in str_list if x != ''][None, 0, "Hi", "Hello"]
>>> lstr = ['hello', '', ' ', 'world', ' ']>>> lstr['hello', '', ' ', 'world', ' ']
>>> ' '.join(lstr).split()['hello', 'world']
>>> filter(None, lstr)['hello', ' ', 'world', ' ']

比较时间

>>> from timeit import timeit>>> timeit('" ".join(lstr).split()', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)4.226747989654541>>> timeit('filter(None, lstr)', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)3.0278358459472656

请注意,filter(None, lstr)不会删除带有空格' '的空字符串,它只会修剪'',而' '.join(lstr).split()会删除两者。

要使用filter()并删除空格字符串,需要更多时间:

>>> timeit('filter(None, [l.replace(" ", "") for l in lstr])', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)18.101892948150635

来自@Ib33X的回复很棒。如果你想删除每个空字符串,在条带化之后。你也需要使用条带方法。否则,如果它有空格,它也会返回空字符串。就像,“”对那个答案也有效。所以,可以通过。

strings = ["first", "", "second ", " "][x.strip() for x in strings if x.strip()]

答案是["first", "second"]
如果你想使用filter方法,你可以这样做
list(filter(lambda item: item.strip(), strings))。这是给出相同的结果。

azizaltofilter(None, lstr)不会删除空格为' '的空字符串,但如果您确定lstr仅包含字符串,则可以使用filter(str.strip, lstr)

>>> lstr = ['hello', '', ' ', 'world', ' ']>>> lstr['hello', '', ' ', 'world', ' ']>>> ' '.join(lstr).split()['hello', 'world']>>> filter(str.strip, lstr)['hello', 'world']

在我的电脑上比较时间

>>> from timeit import timeit>>> timeit('" ".join(lstr).split()', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)3.356455087661743>>> timeit('filter(str.strip, lstr)', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)5.276503801345825

删除''和空格为' '的空字符串的最快解决方案仍然是' '.join(lstr).split()

如注释中所述,如果字符串包含空格,情况就不同了。

>>> lstr = ['hello', '', ' ', 'world', '    ', 'see you']>>> lstr['hello', '', ' ', 'world', '    ', 'see you']>>> ' '.join(lstr).split()['hello', 'world', 'see', 'you']>>> filter(str.strip, lstr)['hello', 'world', 'see you']

您可以看到filter(str.strip, lstr)保留带有空格的字符串,但' '.join(lstr).split()会拆分这些字符串。

总结最佳答案:

1.在不剥离的情况下消除电磁辐射:

也就是说,保留全空格字符串:

slist = list(filter(None, slist))

优点:

  • 最简单;
  • 最快(见下面的基准)。

2.为了消除剥离后的空隙…

2. a…当字符串不包含单词之间的空格时:

slist = ' '.join(slist).split()

优点:

  • 小代码
  • 快(但由于内存问题,大数据集的速度并不快,与@paolo-melchiorre的结果相反)

2.b…当字符串包含单词之间的空格时?

slist = list(filter(str.strip, slist))

优点:

  • 最快;
  • 代码的可理解性。

2018年机器上的基准:

## Build test-data#import random, stringnwords = 10000maxlen = 30null_ratio = 0.1rnd = random.Random(0)                  # deterministic resultswords = [' ' * rnd.randint(0, maxlen)if rnd.random() > (1 - null_ratio)else''.join(random.choices(string.ascii_letters, k=rnd.randint(0, maxlen)))for _i in range(nwords)]
## Test functions#def nostrip_filter(slist):return list(filter(None, slist))
def nostrip_comprehension(slist):return [s for s in slist if s]
def strip_filter(slist):return list(filter(str.strip, slist))
def strip_filter_map(slist):return list(filter(None, map(str.strip, slist)))
def strip_filter_comprehension(slist):  # waste memoryreturn list(filter(None, [s.strip() for s in slist]))
def strip_filter_generator(slist):return list(filter(None, (s.strip() for s in slist)))
def strip_join_split(slist):  # words without(!) spacesreturn ' '.join(slist).split()
## Benchmarks#%timeit nostrip_filter(words)142 µs ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit nostrip_comprehension(words)263 µs ± 19.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit strip_filter(words)653 µs ± 37.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit strip_filter_map(words)642 µs ± 36 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit strip_filter_comprehension(words)693 µs ± 42.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit strip_filter_generator(words)750 µs ± 28.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit strip_join_split(words)796 µs ± 103 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

请记住,如果您想保留字符串中的空格,您可能会使用某些方法无意中删除它们。如果你有这个列表

['你好世界', ' ', '', '你好']你可能想要什么['你好世界','你好']

首先修剪列表以将任何类型的空格转换为空字符串:

space_to_empty = [x.strip() for x in _text_list]

然后从它们列表中删除空字符串

space_clean_list = [x for x in space_to_empty if x]

使用正则表达式和过滤器进行匹配

lstr = ['hello', '', ' ', 'world', ' ']r=re.compile('^[A-Za-z0-9]+')results=list(filter(r.match,lstr))print(results)

你可以用这样的东西

test_list = [i for i in test_list if i]

其中test_list要从中删除空元素的列表。