【问题标题】:Python split string by patternPython按模式拆分字符串
【发布时间】:2013-04-11 19:08:48
【问题描述】:

我有像"aaaaabbbbbbbbbbbbbbccccccccccc" 这样的字符串。 字符数可能不同,有时字符串内可能会有破折号,例如"aaaaa-bbbbbbbbbbbbbbccccccccccc"

有什么聪明的方法可以拆分它"aaaaa","bbbbbbbbbbbbbb","ccccccccccc" 并获取它的索引是拆分还是只获取索引,而不遍历每个字符串?如果破折号位于 to 模式之间,则它可以在左侧或右侧结束,只要它始终处理相同。

有什么想法吗?

【问题讨论】:

    标签: python regex string split


    【解决方案1】:

    使用itertools.groupby怎么样?

    >>> s = 'aaaaabbbbbbbbbbbbbbccccccccccc'
    >>> from itertools import groupby
    >>> [''.join(v) for k,v in groupby(s)]
    ['aaaaa', 'bbbbbbbbbbbbbb', 'ccccccccccc']
    

    这会将- 作为它们自己的子字符串,很容易被过滤掉。

    >>> s = 'aaaaa-bbbbbbbbbbbbbb-ccccccccccc'
    >>> [''.join(v) for k,v in groupby(s) if k != '-']
    ['aaaaa', 'bbbbbbbbbbbbbb', 'ccccccccccc']
    

    【讨论】:

    • 你能想出一个获取索引的好方法吗?我能想到的最好的就是grouped = [(k, list(g)) for k,g in groupby(enumerate(s), key=lambda x: x[1])]; [(k, g[0][0], g[-1][0]) for k,g in grouped]。在 python 3 中,我猜你也可以在长度上使用accumulate
    • @DSM -- 对。我错过了关于索引的部分......不确定一个干净的好方法......
    【解决方案2】:

    正则表达式MatchObject 结果包括匹配的索引。剩下的就是匹配重复的字符:

    import re
    
    repeat = re.compile(r'(?P<start>[a-z])(?P=start)+-?')
    

    仅当给定字母字符 (a-z) 至少重复一次时才匹配:

    >>> for match in repeat.finditer("aaaaabbbbbbbbbbbbbbccccccccccc"):
    ...     print match.group(), match.start(), match.end()
    ... 
    aaaaa 0 5
    bbbbbbbbbbbbbb 5 19
    ccccccccccc 19 30
    

    匹配结果中的.start().end() 方法为您提供输入字符串中的确切位置。

    破折号包含在匹配项中,但不包含非重复字符:

    >>> for match in repeat.finditer("a-bb-cccccccc"):
    ...     print match.group(), match.start(), match.end()
    ... 
    bb- 2 5
    cccccccc 5 13
    

    如果您希望 a- 部分匹配,只需将 + 替换为 * 乘数:

    repeat = re.compile(r'(?P<start>[a-z])(?P=start)*-?')
    

    【讨论】:

    • 我怎样才能保留破折号?例如“aaaaa-”、“bbbbbbbbbbbbbb”、“ccccccccccc”。
    • @Fritz:对不起,我以为你不想要它们。在重新阅读时,我看到你这样做了。我将它们包含在前面的字母中。
    • 太棒了!非常感谢。我想我真的应该更深入地研究正则表达式。
    【解决方案3】:
    str="aaaaabbbbbbbbbbbbbbccccccccccc"
    p = [0] 
    for i, c in enumerate(zip(str, str[1:])):
        if c[0] != c[1]:
            p.append(i + 1)
    print p
    
    # [0, 5, 19]
    

    【讨论】:

      最近更新 更多