从字符串列表中删除空字符串
- 2024-12-12 08:41:00
- admin 原创
- 134
问题描述:
我想从 python 中的字符串列表中删除所有空字符串。
我的想法是这样的:
while '' in str_list:
str_list.remove('')
有没有更符合 Python 风格的方法来做到这一点?
解决方案 1:
我会用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))
解决方案 2:
使用列表推导是最 Python 的方式:
>>> strings = ["first", "", "second"]
>>> [x for x in strings if x]
['first', 'second']
如果必须就地修改列表,因为还有其他引用必须看到更新的数据,那么使用切片分配:
strings[:] = [x for x in strings if x]
解决方案 3:
过滤器实际上对此有一个特殊的选项:
filter(None, sequence)
它将过滤掉所有结果为 False 的元素。这里无需使用实际的可调用函数,例如 bool、len 等。
它和 map(bool, ...) 一样快
解决方案 4:
>>> 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
解决方案 5:
总结最佳答案:
无需剥离即可消除空瓶:
也就是说,所有空格字符串都被保留:
slist = list(filter(None, slist))
优点:
最簡單;
最快(见下面的基准)。
清除清废后的空瓶...
2.a...当字符串不包含单词之间的空格时:
slist = ' '.join(slist).split()
优点:
小码
速度快(但由于内存问题,处理大数据集时速度不是最快的,与@paolo-melchiorre 的结果相反)
2.b...当字符串包含单词之间的空格时?
slist = list(filter(str.strip, slist))
优点:
最快;
代码的可理解性。
2018 年机器上的基准:
## Build test-data
#
import random, string
nwords = 10000
maxlen = 30
null_ratio = 0.1
rnd = random.Random(0) # deterministic results
words = [' ' * 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 memory
return 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(!) spaces
return ' '.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)
解决方案 6:
@Ib33X 的回复很棒。如果您想在删除后删除每个空字符串。您也需要使用 strip 方法。否则,如果字符串中有空格,它也会返回空字符串。例如,“ ”对于该答案也有效。因此,可以通过以下方式实现。
strings = ["first", "", "second ", " "]
[x.strip() for x in strings if x.strip()]
答案是["first", "second"]
。
如果您想使用filter
方法,可以这样做
list(filter(lambda item: item.strip(), strings))
。这会产生相同的结果。
解决方案 7:
我将使用 if X != '' 而不是 if x,以便消除空字符串。如下所示:
str_list = [x for x in str_list if x != '']
这将在列表中保留 None 数据类型。此外,如果列表包含整数,并且 0 是其中之一,它也将被保留。
例如,
str_list = [None, '', 0, "Hi", '', "Hello"]
[x for x in str_list if x != '']
[None, 0, "Hi", "Hello"]
解决方案 8:
你可以使用类似这样的东西
test_list = [i for i in test_list if i]
其中 test_list 是要从中删除空元素的列表。
解决方案 9:
根据列表的大小,使用 list.remove() 而不是创建新列表可能会最有效:
l = ["1", "", "3", ""]
while True:
try:
l.remove("")
except ValueError:
break
这样做的好处是不需要创建新的列表,但缺点是每次都必须从头开始搜索,尽管与while '' in l
上面建议的使用方法不同,它只需要在每次出现时搜索一次''
(当然有一种方法可以兼具两种方法的优点,但它更复杂)。
解决方案 10:
据Aziz Alto filter(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()
会拆分这些字符串。
解决方案 11:
请记住,如果您想保留字符串中的空格,您可能会使用某些方法无意中删除它们。如果您有此列表
['hello world', ' ', '', 'hello'] 你可能想要什么 ['hello world','hello']
首先修剪列表以将任何类型的空格转换为空字符串:
space_to_empty = [x.strip() for x in _text_list]
然后从列表中删除空字符串
space_clean_list = [x for x in space_to_empty if x]
解决方案 12:
使用filter
:
newlist=filter(lambda x: len(x)>0, oldlist)
使用过滤器的缺点是它比其他方法慢;而且lambda
通常成本较高。
或者你可以选择最简单、最具迭代性的方法:
# I am assuming listtext is the original list containing (possibly) empty items
for item in listtext:
if item:
newlist.append(str(item))
# You can remove str() based on the content of your original list
这是最直观的方法,并且可以在适当的时间内完成。
解决方案 13:
使用正则表达式和过滤器进行匹配
lstr = ['hello', '', ' ', 'world', ' ']
r=re.compile('^[A-Za-z0-9]+')
results=list(filter(r.match,lstr))
print(results)
解决方案 14:
这对我有用。我也有 nan 值,因为我是从 pandas dataframe 列值创建此列表的。
[x for x in a if pd.notna(x) and x.strip()]