如何从列表末尾删除 None 的所有实例?

发布于 2025-01-09 00:06:50 字数 555 浏览 0 评论 0原文

Python 有一个名为 rstrip() 的字符串方法:

>>> s = "hello world!!!"
>>> s.rstrip("!")
'hello world'

我想为 Python 列表实现类似的功能。也就是说,我想从列表末尾删除给定值的所有实例。在本例中,该值为None

这是一些开始的例子:

[1, 2, 3, None]
[1, 2, 3, None, None, None]
[1, 2, 3, None, 4, 5]
[1, 2, 3, None, None, 4, 5, None, None]

我希望最终结果是:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3, None, 4, 5]
[1, 2, 3, None, None, 4, 5]

这是到目前为止我的解决方案:

while l[-1] is None:
    l.pop()

Python has a string method called rstrip():

>>> s = "hello world!!!"
>>> s.rstrip("!")
'hello world'

I want to implement similar functionality for a Python list. That is, I want to remove all instances of a given value from the end of a list. In this case, the value is None.

Here's some starting examples:

[1, 2, 3, None]
[1, 2, 3, None, None, None]
[1, 2, 3, None, 4, 5]
[1, 2, 3, None, None, 4, 5, None, None]

I want the end results to be:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3, None, 4, 5]
[1, 2, 3, None, None, 4, 5]

Here's my solution so far:

while l[-1] is None:
    l.pop()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

渡你暖光 2025-01-16 00:06:50

如果您想就地修改列表,那么您的解决方案很好,只需确保处理列表为空时的情况:

while l and l[-1] is None:
    l.pop()

如果您想计算一个新列表,您可以将您的解决方案调整为:

def stripNone(l):
    if not l:
        return []
    
    rlim = 0
    for x in reversed(l):
        if x is None:
            rlim += 1
        else:
            break
    
    return l[: len(l) - rlim]

还有 < a href="https://docs.python.org/3/library/itertools.html#itertools.dropwhile" rel="nofollow noreferrer">itertools.dropwhile,但是你必须执行两个逆转:

def stripNone(l):
    return list(dropwhile(lambda x: x is None, l[::-1]))[::-1]

If you want to modify the list in-place, then your solution is good, just make sure you handle the case when the list is empty:

while l and l[-1] is None:
    l.pop()

If you want to compute a new list, you can adapt your solution into:

def stripNone(l):
    if not l:
        return []
    
    rlim = 0
    for x in reversed(l):
        if x is None:
            rlim += 1
        else:
            break
    
    return l[: len(l) - rlim]

There is also itertools.dropwhile, but you have to perform two reversals:

def stripNone(l):
    return list(dropwhile(lambda x: x is None, l[::-1]))[::-1]
抽个烟儿 2025-01-16 00:06:50

另外两个版本也适用于仅 None 的列表:

while None in l[-1:]:
    l.pop()
for x in reversed(l):
    if x is not None:
        break
    l.pop()

l = [None] * 10**3 上的一些解决方案进行基准测试:

 83 us  stripNone1
137 us  stripNone2
 60 us  stripNone3
 42 us  stripNone3b
 53 us  stripNone4
 34 us  stripNone5
 19 us  stripNone6

请注意 stripNone2stripNone6 有一个小缺陷:如果 Trailline None 中有一个对象不是 None 但声称​​等于 None,那么它将被删除。不过,这样的物体非常不寻常。也许人们实际上也想要删除这样一个对象。

基准代码:

def stripNone1(l):
    while l and l[-1] is None:
        l.pop()

def stripNone2(l):
    while None in l[-1:]:
        l.pop()

def stripNone3(l):
    for x in reversed(l):
        if x is not None:
            break
        l.pop()

def stripNone3b(l):
    pop = l.pop
    for x in reversed(l):
        if x is not None:
            break
        pop()

def stripNone4(l):
    for i, x in enumerate(reversed(l), 1):
        if x is not None:
            del l[-i:]
            break

def stripNone5(l):
    pop = l.pop
    try:
        while (last := pop()) is None:
            pass
        l.append(last)
    except IndexError:
        pass

def stripNone6(l):
    while l:
        chunk = l[-32:]
        if chunk.count(None) < len(chunk):
            while l[-1] is None:
                l.pop()
            break
        del l[-32:]

from timeit import repeat
solutions = stripNone1, stripNone2, stripNone3, stripNone3b, stripNone4, stripNone5, stripNone6
for i in range(3):
    print(f'Round {i+1}:')
    for sol in solutions:
        ls = [[42] * head + [None] * tail
              for _ in range(5)
              for head in range(0, 2001, 200)
              for tail in range(0, 2001, 200)]
        number = len(ls) // 5
        ls = iter(ls)
        time = min(repeat(lambda: sol(next(ls)), number=number)) / number
        print(f'{int(time * 10**6):3d} us  {sol.__name__}')

Two more versions that also work for None-only lists:

while None in l[-1:]:
    l.pop()
for x in reversed(l):
    if x is not None:
        break
    l.pop()

Benchmarking some solutions on l = [None] * 10**3:

 83 us  stripNone1
137 us  stripNone2
 60 us  stripNone3
 42 us  stripNone3b
 53 us  stripNone4
 34 us  stripNone5
 19 us  stripNone6

Note that stripNone2 and stripNone6 have a small flaw: If there's an object among the trailine Nones that isn't None but claims to equal None, then it'll get removed. Such an object would be highly unusual, though. And perhaps one would actually want to remove such an object as well.

Benchmark code:

def stripNone1(l):
    while l and l[-1] is None:
        l.pop()

def stripNone2(l):
    while None in l[-1:]:
        l.pop()

def stripNone3(l):
    for x in reversed(l):
        if x is not None:
            break
        l.pop()

def stripNone3b(l):
    pop = l.pop
    for x in reversed(l):
        if x is not None:
            break
        pop()

def stripNone4(l):
    for i, x in enumerate(reversed(l), 1):
        if x is not None:
            del l[-i:]
            break

def stripNone5(l):
    pop = l.pop
    try:
        while (last := pop()) is None:
            pass
        l.append(last)
    except IndexError:
        pass

def stripNone6(l):
    while l:
        chunk = l[-32:]
        if chunk.count(None) < len(chunk):
            while l[-1] is None:
                l.pop()
            break
        del l[-32:]

from timeit import repeat
solutions = stripNone1, stripNone2, stripNone3, stripNone3b, stripNone4, stripNone5, stripNone6
for i in range(3):
    print(f'Round {i+1}:')
    for sol in solutions:
        ls = [[42] * head + [None] * tail
              for _ in range(5)
              for head in range(0, 2001, 200)
              for tail in range(0, 2001, 200)]
        number = len(ls) // 5
        ls = iter(ls)
        time = min(repeat(lambda: sol(next(ls)), number=number)) / number
        print(f'{int(time * 10**6):3d} us  {sol.__name__}')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文