【问题标题】:Trailing empty string after re.split()re.split() 后尾随空字符串
【发布时间】:2021-10-20 12:43:20
【问题描述】:

我有两个字符串,我想将数字序列与其他所有内容隔离开来。

例如:

import re
s = 'abc123abc'
print(re.split('(\d+)', s))
s = 'abc123abc123'
print(re.split('(\d+)', s))

输出如下:

['abc', '123', 'abc']
['abc', '123', 'abc', '123', '']

请注意,在第二种情况下,后面有一个空字符串。

显然我可以对此进行测试并在必要时将其删除,但这似乎很麻烦,我想知道是否可以改进 RE 以解决这种情况。

【问题讨论】:

  • 你真的想要['123', '123']作为结果吗?
  • 在这种情况下,你可以使用s.strip("1234567890"),但是对于一个更复杂的正则表达式你会怎么做呢?
  • 无论如何,IMO 这是 Python - re.split: extra empty strings that the beginning and end list 的副本,除非 OP 确实想要 ['123', '123'],在这种情况下,解决方案是使用 findall,而不是 split
  • @mkrieger1 我应该更清楚我的问题。对不起。我想要如图所示的输出,但没有尾随的空字符串。使用 filter 可以满足我的需要

标签: python python-re


【解决方案1】:

你可以使用filter,不要像下面这样返回这个空字符串:

>>> s = 'abc123abc123'
>>> re.split('(\d+)', s)
['abc', '123', 'abc', '123', '']

>>> list(filter(None,re.split('(\d+)', s)))
['abc', '123', 'abc', '123']

感谢@chepner,您可以生成如下列表理解:

>>> [x for x in re.split('(\d+)', s) if x]
['abc', '123', 'abc', '123']

如果你有符号或其他你需要split:

>>> s = '&^%123abc123$#@123'
>>> list(filter(None,re.split('(\d+)', s)))
['&^%', '123', 'abc', '123', '$#@', '123']

【讨论】:

  • 您还可以使用列表推导式或生成器表达式,以及x for x in re.split(...) if x
  • 过度生成然后过滤并不优雅。尤其是当 OP 声明他们可以轻松做到但不想这样做时。
【解决方案2】:

这与re.split() 本身的实现有关:您无法更改它。当函数拆分时,它不会检查捕获组之后的任何内容,因此它无法选择保留或丢弃拆分后留下的空字符串。它只是在那里分裂并将字符串的其余部分(可以为空)留给下一个循环。

如果您不想要那个空字符串,您可以在将结果收集到列表之前以各种方式将其删除。 user1740577 就是一个例子,但我个人更喜欢列表理解,因为它更适合简单的过滤器/映射操作:

parts = [part for part in re.split('(\d+)', s) if part]

我建议不要在列表已经创建之后检查和删除元素,因为它涉及更多的操作和分配。

【讨论】:

    【解决方案3】:

    为此使用正则表达式的一种简单方法是re.findall

    def bits(s):
        return re.findall(r"(\D+|\d+)", s)
    
    bits("abc123abc123")
    # ['abc', '123', 'abc', '123']
    

    但使用itertools.groupby 似乎更容易、更自然。毕竟,您是基于单个条件对可迭代对象进行分块:

    from itertools import groupby
    
    def bits(s):
        return ["".join(g) for _, g in groupby(s, key=str.isdigit)]
    
    bits("abc123abc123")
    # ['abc', '123', 'abc', '123']
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      • 2018-09-26
      • 2018-04-15
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      相关资源
      最近更新 更多