各文字の3番目、4番目、...の出現に一致するregex
パターンを探しています。明確にするために以下を見てください:
たとえば、次の文字列があります。
111aabbccxccybbzaa1
2回目以降の重複文字をすべて置換したい。出力は次のようになります。
11-aabbccx--y--z---
これまでに試したいくつかの正規表現パターン:
次の正規表現を使用して、各文字の最後の出現を見つけることができます: (.)(?=.*\1)
または、これを使用して、連続する重複にはそれを行うことができますが、重複にはできません: ([a-zA-Z1-9])\1{2,}
非正規表現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
_であり、x
で_1
_が4回発生した場合、rowid(x)
の最後の要素は_4
_です。
これは正規表現なしで簡単に実現できます。
_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---
_
仕組み:
for u in set(s)
は、文字列内の一意の文字のリストを取得します:_{'c','a','b','y','1','z','x'}
_for i in ...
_は、3で収集したインデックスをループします。[i for i in range(len(s)) if s[i]==u][2:]
は、文字列の各文字をループし、それがu
と一致するかどうかを確認し(手順1から)、2番目の要素から最後まで配列をスライスします(最初の2つの要素を削除します)。それらが存在する場合)s[:i]+'-'+s[i+1:]
_に設定します-インデックスまでの部分文字列を_-
_と連結し、次にインデックスの後の部分文字列を連結して、元の文字を効果的に省略します。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'
正規表現なしpython one-liner:
s = "111aabbccxccybbzaa1"
print("".join(char if s.count(char, 0, i) < 2 else "-" for i, char in enumerate(s)))
# ==> "11-aabbccx--y--z---"
これは文字列を列挙し、その後ろにある現在の文字の出現回数を数え、最初の2文字の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---
おかげで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---
スニペット 。