是否有一种优雅的蟒蛇方法可以从列表中删除尾随的空元素。一种list.rstrip(无)。所以
[1, 2, 3, None, 4, None, None]
应该导致
[1, 2, 3, None, 4]
我想这可以推广到删除任何特定值的尾随元素。
UPDATE :我应该指定我希望将其作为单行(可读)表达式完成
答案 0 :(得分:18)
已修改:使用pop()而非切片列表,因为评论者已正确建议。
我不知道是否有更多的pythonic方式,但这有效:
my_list = [1, 2, 3, None, 4, None, None]
while not my_list[-1]:
my_list.pop()
print my_list
>>>[1, 2, 3, None, 4]
修改:正如@DSM指出的那样,如果你只想摆脱None
值,并留下零或其他假值,你可以这样做:
while my_list and my_list[-1] is None:
my_list.pop()
答案 1 :(得分:7)
以下显式检查None
元素:
while l and l[-1] is None:
l.pop()
可以概括如下:
f = lambda x: x is None
while l and f(l[-1]):
l.pop()
您现在可以为f
定义不同的功能,以检查其他条件。
答案 2 :(得分:4)
def remove_trailing( l, remove_value=None):
i = len(l)
while i>0 and l[i-1] == remove_value:
i -= 1
return l[:i]
答案 3 :(得分:3)
试试这个
>>> x=[1, 2, 3, None, 4, None, None]
>>> while x[-1] is None:
x.pop()
答案 4 :(得分:2)
我从未接受过答案,因为我对提供的解决方案并不满意。这是另一个解决方案(1行,没有库依赖),我对它们都不满意:
a = [1, 2, None, 3, None, None]
reduce(lambda l, e: [e]+l if l or e is not None else [], reversed(a), [])
答案 5 :(得分:1)
对于单行解决方案:
In [30]: from itertools import dropwhile
In [31]: list(reversed(tuple(dropwhile(lambda x: x is None, reversed([1, 2, 3, None, 4, None, None])))))
Out[31]: [1, 2, 3, None, 4]
如果你想重复使用它,这里有一个无点样式的定义:
In [36]: from functional import compose, partial
In [37]: varargs = lambda *args: args
In [38]: compose_mult = compose(partial(reduce, compose),varargs) # compose which takes variable number of arguments. Innermost function to the right.
In [39]: compose_mult(list, reversed, tuple, partial(dropwhile, lambda x: x is None), reversed)([1, 2, 3, None, 4, None, None])
Out[39]: [1, 2, 3, None, 4]
答案 6 :(得分:1)
如果您正在寻找单行,可能是这样的:
a = [1, 2, 3, None, 4, None, None]
b = [x for n, x in enumerate(a) if any(y is not None for y in a[n:])]
print b
请注意,它是二次的(在最坏的情况下)。
对于任何虚假价值,它甚至更简单:
b = [x for n, x in enumerate(a) if any(a[n:])]
答案 7 :(得分:1)
如果你真的需要妥协可读性,我就会这样做。
>>> from itertools import takewhile
>>> l=[1,2,3,None,4,5,None,None]
>>> l[:-len(list(takewhile(lambda x: x==None, reversed(l))))]
[1,2,3,None,4,5]
答案 8 :(得分:0)
这是另一个单行:
>>> l = [1, 2, 3, None, 4, None, None]
>>> [l[i] for i in range(len("".join(map(lambda x: {None: " "}.get(x, "_"), l)).rstrip()))]
[1, 2, 3, None, 4]
这些东西很有趣!
修改强>
我刚刚意识到列表理解是完全没必要的。切片应该可以正常工作:
>>> l[:len("".join(map(lambda x: {None: " "}.get(x, "_"), l)).rstrip())]
答案 9 :(得分:0)
递归+切片怎么样?
>>> rstrip = lambda x, elts=(None,): rstrip(x[:-1], elts) if x and x[-1] in elts else x
>>> rstrip([1, 2, 3, None])
[1, 2, 3]
>>> rstrip([1, 2, 3, None], (None, 3))
[1, 2]
注意:我假设你不是在寻找计算效率最高的解决方案......
答案 10 :(得分:0)
怎么样:
[a[i] for i in range(len(a)) if a[i:] != [None] * (len(a) - i) ]
答案 11 :(得分:0)
more_itertools
项目为任何可迭代实现rstrip
:
iterable = [1, 2, 3, None, 4, None, None]
list(mit.rstrip(iterable, lambda x: x in {None}))
# [1, 2, 3, None, 4]
more_itertools.rstrip
接受可迭代和谓词。有关详细信息,请参阅source code。