删除重复的字母,缩写除外

Remove duplicated letters except in abbreviations

只要有更多的字母,我就想从字符串中删除重复的字母。例如,考虑以下列表:

aaa --> it is untouched because all are the same letters
aa  --> it is untouched because all are the same letters
a   --> not touched, just one letter
broom --> brom
school --> schol
boo --> should be bo
gool --> gol
ooow  --> should be ow

我使用以下正则表达式来删除重复项,如下所示:

(?<=[a-zA-Z])([a-zA-Z])+(?=[a-zA-Z])

但是,这在字符串 boo 中失败,它保留为原始 boo 而不是删除双 o。 oow 也会发生同样的情况,它不会减少到 ow.

你知道为什么 boo 没有被正则表达式带走吗?

您可以将由相同字符组成的整个单词匹配并捕获到一个捕获组中,然后在所有其他上下文中匹配重复的连续字母,并进行相应替换:

import re
text = "aaa, aa, a,broom, school...boo, gool, ooow."
print( re.sub(r'\b(([a-zA-Z])+)\b|([a-zA-Z])+', r'', text) )
# => aaa, aa, a,brom, schol...bo, gol, ow.

参见Python demo and the regex demo

正则表达式详细信息

  • \b - 单词边界
  • (([a-zA-Z])+) - 第 1 组:一个 ASCII 字母(捕获到第 2 组),然后同一字母出现一次或多次
  • \b - 单词边界
  • | - 或
  • ([a-zA-Z]) - 第 3 组:捕获到第 3 组的 ASCII 字母
  • + - 在第 3 组中出现一次或多次捕获的字母。

替换是第 1 组和第 3 组值的串联。

要匹配任何 Unicode 字母,请将 [a-zA-Z] 替换为 [^\W\d_]

您的正则表达式与 boo 不匹配,因为它搜索前后至少有一个不同字符的重复项。

一种可能性是制作一个更简单的正则表达式来捕获所有重复项,然后在结果是一个字符时还原

def remove_duplicate(string):
    new_string = re.sub(r'([a-zA-Z])+', r'', string)
    return new_string if len(new_string) > 1 else string

这是一个没有正则表达式的可能解决方案。它速度更快,但它也会删除重复的白色 space 和标点符号。不仅是字母。

def remove_duplicate(string):
    new_string = ''
    last_c = None
    for c in string:
        if c == last_c:
            continue
        else:
            new_string += c
            last_c = c
    if len(new_string) > 1:
        return new_string
    else:
        return string