我的想法看起来像这样:
while '' in str_list:
str_list.remove('')
有没有更符合 Python 风格的方法来完成这个任务?
我会使用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))
itertools
模块中的ifilter
函数是更快的选择—— >>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
得到结果 2.3468542098999023
; >>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)
得到结果 0.04442191123962402
。 - Humphrey Bogartifilter
时,结果是惰性地评估的,而不是一次性评估——我认为对于大多数情况来说,ifilter
更好。有趣的是,使用filter
仍然比在ifilter
中包装一个list
要快。 - Humphrey Bogart使用列表推导式是最符合Python风格的方式:
>>> strings = ["first", "", "second"]
>>> [x for x in strings if x]
['first', 'second']
如果必须在原地修改列表,因为还有其他引用需要看到更新后的数据,则使用切片赋值:strings[:] = [x for x in strings if x]
[x for x in strings if x.strip()]
。 - Bondif x
中),它们会被视为假。方括号、for
循环和 if
子句组合起来的含义是:“如果 x
实际上包含某些内容,则为 strings
中的每个元素生成一个由 x
组成的列表。” @Ib33x 做得非常棒。这个答案绝对是最符合Python风格的。 - Nat Riddle[x for x in strings if x.strip()]
可以去除空格字符串。 - PatrickT在此情况下,筛选器实际上具有特殊选项:
filter(None, sequence)
它将过滤掉所有评估为False的元素。在这里不需要使用实际的可调用对象(如bool、len等)。
它和map(bool, ...)一样快。
>>> 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
filter(None, lstr)
不会删除带有空格 ' '
的空字符串。是的,因为那不是一个空字符串。 - AMC也就是说,所有的空格字符串都会被保留:
slist = list(filter(None, slist))
优点:
slist = ' '.join(slist).split()
优点:
slist = list(filter(str.strip, slist))
优点:
## 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)
s and s.strip()
可以简化为 s.strip()
。 - AMCfilter(None, words)
,则需要使用s and s.strip()
。我已经更正了上面的两个示例函数,并删除了两个错误的函数。 - ankostis@Ib33X的回复很棒。如果你想删除所有空字符串,剥离后需要使用strip方法。否则,如果有空格,它也会返回空字符串。例如," "对于该答案也是有效的。所以可以通过以下方式实现。
strings = ["first", "", "second ", " "]
[x.strip() for x in strings if x.strip()]
这个答案将是["first", "second"]
。
filter
方法,你可以这样做
list(filter(lambda item: item.strip(), strings))
。这会得到相同的结果。我会使用 if X != '' 代替 if x,以消除空字符串。就像这样:
if X != '':
str_list = [x for x in str_list if x != '']
这将保留您列表中的None数据类型。此外,如果您的列表包含整数,并且其中之一为0,则0也将被保留。
例如,
str_list = [None, '', 0, "Hi", '', "Hello"]
[x for x in str_list if x != '']
[None, 0, "Hi", "Hello"]
str_list = [None, '', 0, "Hi", '', "Hello"]
,那么这是一个设计不良的应用程序的迹象。你不应该在同一个列表中拥有多个接口(类型)和 None。 - Tritium21你可以使用类似这样的东西
test_list = [i for i in test_list if i]
其中test_list是您想要删除空元素的列表。
根据你的列表大小,如果使用list.remove()而不是创建一个新列表可能会更有效:
l = ["1", "", "3", ""]
while True:
try:
l.remove("")
except ValueError:
break
这种方法的优点是不会创建新列表,但缺点是每次都要从开头开始搜索,尽管与上面提出的使用while '' in l
不同,它只需要每个''
出现时搜索一次(当然有一种方法可以保留两种方法的优点,但更加复杂)。
ary[:] = [e for e in ary if e]
。这种方法更加简洁,而且不会使用异常来控制流程。 - Krzysztof Karskifilter(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()
将拆分这些字符串。join
解决方案将使用空格拆分字符串,但过滤器不会。感谢您的评论,我改进了我的答案。 - Paolo Melchiorre
for x in list
迭代列表时,您永远不应该修改该列表。如果您使用while loop
,则可以这样做。演示的循环将删除空字符串,直到没有更多的空字符串为止,然后停止。实际上,我甚至没有看问题(只看了标题),但我给出了完全相同的循环作为可能性!如果您不想出于内存考虑使用 comprehensions 或 filters,则这是一种非常 Pythonic 的解决方案。 - aaronasterlingfor var in list:
的形式,那么他会进行遍历。但是在这里,他写成了while const in list:
的形式。这并不是在遍历任何内容,它只是在满足条件为假之前一直重复相同的代码。 - Camiondata = list(filter(None, str_list))
- Jacob Ward