匹配每个字符出现的多个(3+)次

时间:2019-12-11 20:36:06

标签: python r regex string

我正在寻找一种regex模式,该模式将与每个字符的第三,第四,...匹配。请在下面进行澄清:

例如,我有以下字符串:

111aabbccxccybbzaa1

我想在第二次出现后替换所有重复的字符。输出将是:

11-aabbccx--y--z---

到目前为止我尝试过的一些正则表达式模式:

使用以下正则表达式,我可以找到每个字符的最后一次出现:(.)(?=.*\1)

或者使用此方法,我可以将其用于连续重复,但不能重复:([a-zA-Z1-9])\1{2,}

6 个答案:

答案 0 :(得分:6)

非正则表达式R解决方案。分割字串。用'-'替换该rowid> = 3 *的向量的元素。粘贴回去。

x <- '111aabbccxccybbzaa1'

xsplit <- strsplit(x, '')[[1]]
xsplit[data.table::rowid(xsplit) >= 3] <- '-'
paste(xsplit, collapse = '')

# [1] "11-aabbccx--y--z---"

* rowid(x)是一个整数向量,每个元素表示实现x的相应元素的值的次数。因此,如果x的最后一个元素是1,并且这是1中第四次出现x,那么rowid(x)的最后一个元素就是{{1 }}。

答案 1 :(得分:3)

您无需使用正则表达式即可轻松完成此操作:

See code in use here

s = '111aabbccxccybbzaa1'

for u in set(s):
    for i in [i for i in range(len(s)) if s[i]==u][2:]:
        s = s[:i]+'-'+s[i+1:]

print(s)

结果:

11-aabbccx--y--z---

这是如何工作的:

  1. for u in set(s)获取字符串中的唯一字符列表:{'c','a','b','y','1','z','x'}
  2. for i in ...遍历我们在3中收集的索引。
  3. [i for i in range(len(s)) if s[i]==u][2:]遍历字符串中的每个字符,并检查它是否与u匹配(从步骤1开始),然后将数组从第二个元素切到结尾(删除前两个元素)如果存在)
  4. 将字符串设置为s[:i]+'-'+s[i+1:]-用-将子字符串连接到索引,然后将索引后面的子字符串连接起来,从而有效地省略了原始字符。

答案 2 :(得分:3)

带有gsubfn

的选项
library(gsubfn)
p <- proto(fun = function(this, x) if (count >=3) '-' else x)
for(i in c(0:9, letters)) x <- gsubfn(i, p, x)
x
#[1] "11-aabbccx--y--z---"

数据

x <- '111aabbccxccybbzaa1'

答案 3 :(得分:1)

使用pandas的另一种方法。

import pandas as pd

s = '111aabbccxccybbzaa1'
# 11-aabbccx--y--z---

df = pd.DataFrame({'Data': list(s)})
df['Count'] = 1
df['cumsum'] = df[['Data', 'Count']].groupby('Data').cumsum()
df.loc[df['cumsum']>=3, 'Data'] = '-'
''.join(df.Data.to_list())

输出

11-aabbccx--y--z---

答案 4 :(得分:1)

没有正则表达式python单行代码:

s = "111aabbccxccybbzaa1"

print("".join(char if s.count(char, 0, i) < 2 else "-" for i, char in enumerate(s)))
# ==> "11-aabbccx--y--z---"

这将枚举整个字符串,计算当前字符在其后的出现次数,并且仅在该字符是前2个字符之一(否则为破折号)时才将其放置。

答案 5 :(得分:0)

感谢 WiktorStribiżew Stefan Pochmann 气泡泡泡。为了完整起见,我将发布评论中讨论的可能的regex解决方案;

这仅可用于支持无限宽后向查找的正则表达式。使用Python PyPi regex模块,我们可以执行以下操作:

#python 2.7.12
import regex

s = "111aabbccxccybbzaa1"
print(regex.sub(r'(.)(?<=^(?:(?:(?!\1).)*\1){2,}(?:(?!\1).)*\1)', '-', s)) #Wiktor Stribizew
     ## 11-aabbccx--y--z---
print(regex.sub(r'(.)(?<=(.*\1){3})', '-', s)) #Stefan Pochmann
     ## 11-aabbccx--y--z---
print(regex.sub(r'(.)(?<=(?:.*\1){3})', '-', s)) #Wiktor Stribizew
     ## 11-aabbccx--y--z---
print(regex.sub(r'(.)(?<=(?:\1.*?){2}\1)', '-', s)) #bobble bubble
     ## 11-aabbccx--y--z---

See code in use.