代码之家  ›  专栏  ›  技术社区  ›  vrintle Jake

Python re.sub()并不是替换所有匹配项

  •  2
  • vrintle Jake  · 技术社区  · 6 年前

    我使用的是Python 3,我有两个字符串: abbcabb abca . 我想删除每一个重复出现的 单个字符

    阿巴卡布 应该给 c abca bc .

    我试过下面的正则表达式( here ):

    (.)(.*?)\1
    

    here ):

    (.)(.*?)*?\1
    

    但是,这一次又给出了错误的输出。这里怎么了?


    python代码是一条打印语句:

    print(re.sub(r'(.)(.*?)\1', '\g<2>', s)) # s is the string
    
    5 回复  |  直到 6 年前
        1
  •  3
  •   JON    6 年前

    它可以在没有正则表达式的情况下求解,如下所示

    >>>''.join([i for i in s1 if s1.count(i) == 1])
    'bc'
    >>>''.join([i for i in s if s.count(i) == 1])
    'c'
    
        2
  •  2
  •   Barmar 0___________    6 年前

    re.sub() 不执行重叠替换。在它替换第一场比赛之后,它开始关注比赛的结束。因此,当您在上执行替换时

    abbcabb
    

    abbca 具有 bbc bb 使用空字符串。它不会回去寻找另一场比赛 英国广播公司

    如果需要,您需要编写自己的循环。

    while True:
        newS = re.sub(r'(.)(.*?)\1', r'\g<2>', s)
        if newS == s:
            break
        s = newS
    print(newS)
    

    DEMO

        3
  •  2
  •   Jean-François Fabre    6 年前

    正则表达式似乎不是理想的解决方案

    this answer ,但使用 count 在一个列表中重复,每次都在所有元素上循环。

    O(n**2) 只是复杂性 O(n) collections.Counter

    • 首先,非常容易地计算字符串的字符数&迅速地
    • 然后使用我们刚刚创建的计数器过滤字符串测试计数是否匹配。

    这样地:

    import collections
    
    s = "abbcabb"
    
    cnt = collections.Counter(s)
    
    s = "".join([c for c in s if cnt[c]==1])
    

        4
  •  1
  •   Karl Knechtel Jaikishan    6 年前

    编辑:基于评论交换-如果您只关心字母计数的奇偶性,那么 我不想要正则表达式 相反,我们想要一种类似于@jon推荐的方法。(如果您不关心顺序,那么使用很长字符串的更高效方法可能会使用 collections.Counter


    我对您试图匹配的内容的最佳猜测是:“一个或多个字符-称此子模式为A-后跟一组不同的一个或多个字符-称此子模式为B-再次后跟子模式A”。

    + 作为“一个或多个”的快捷方式(而不是指定一次然后使用 * 对于其余的匹配),但无论哪种方式,您都需要正确地获取子模式。让我们试试:

    >>> import re
    >>> pattern = re.compile(r'(.+?)(.+?)\1')
    >>> pattern.sub('\g<2>', 'abbcabbabca')
    'bbcbaca'
    

    a 在字符串中-它 毕竟是晚一点出现。因此,如果我们使用贪婪匹配,Python将回溯,直到找到一个子模式a的模式,该模式仍然允许a-B-a模式出现:

    >>> pattern = re.compile(r'(.+)(.+?)\1')
    >>> pattern.sub('\g<2>', 'abbcabbabca')
    'cbc'
    

    我觉得不错。

        5
  •  0
  •   Paritosh Singh    6 年前

    网站解释得很好,悬停并使用解释部分。

    (.)(.*?)\1

    那么,为了 abbcabb “三明治”部分应为 bbc 两人之间 a

    编辑: 您可以在不使用正则表达式的情况下尝试以下操作:

    string = "abbcabb"
    result = []
    for i in string:
        if i not in result:
            result.append(i)
        else:
            result.remove(i)
    print(''.join(result))
    

    请注意,这将生成字符串的“最后一次”奇数出现,而不是第一次。

    对于“第一次”已知事件,应使用本节中建议的计数器 answer . 只需更改条件以检查奇数计数。 pseudo code(count[letter] %2 == 1)

    推荐文章