我想从python中的字符串列表中删除所有空字符串。
我的想法看起来像这样:
while '' in str_list:str_list.remove('')
有没有其他的Pythonic方法来做到这一点?
使用列表理解是最Pythonic的方式:
>>> strings = ["first", "", "second"]>>> [x for x in strings if x]['first', 'second']
如果必须就地修改列表,因为还有其他引用必须看到更新的数据,那么使用切片赋值:
strings[:] = [x for x in strings if x]
我会使用filter:
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()的调用中
list()
str_list = list(filter(None, str_list))
根据列表的大小,使用list.remove()而不是创建一个新列表可能是最有效的:
l = ["1", "", "3", ""] while True:try:l.remove("")except ValueError:break
这具有不创建新列表的优点,但缺点是每次都必须从头开始搜索,尽管与上面提出的使用while '' in l不同,它只需要每次出现''搜索一次(当然有一种方法可以保持两种方法的最佳效果,但它更复杂)。
while '' in l
''
过滤器实际上有一个特殊的选项:
filter(None, sequence)
它将过滤掉所有计算为False的元素。这里不需要使用实际的可调用对象,例如bool、len等。
它和map一样快(bool,…)
使用filter:
newlist=filter(lambda x: len(x)>0, oldlist)
使用过滤器的缺点是它比替代品慢;此外,lambda通常是昂贵的。
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(None, lstr)
' '
' '.join(lstr).split()
要使用filter()并删除空格字符串,需要更多时间:
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))。这是给出相同的结果。
["first", "second"]
list(filter(lambda item: item.strip(), strings))
azizaltofilter(None, lstr)不会删除空格为' '的空字符串,但如果您确定lstr仅包含字符串,则可以使用filter(str.strip, 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()会拆分这些字符串。
也就是说,保留全空格字符串:
slist = list(filter(None, slist))
优点:
slist = ' '.join(slist).split()
slist = list(filter(str.strip, slist))
## 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要从中删除空元素的列表。