Estou procurando um regex
padrão que corresponda à terceira, quarta, ... ocorrência de cada personagem. Veja abaixo os esclarecimentos:
Por exemplo, eu tenho a seguinte string:
111aabbccxccybbzaa1
Quero substituir todos os caracteres duplicados após a segunda ocorrência. A saída será:
11-aabbccx--y--z---
Alguns padrões de regex que eu tentei até agora:
Usando o seguinte regex, posso encontrar a última ocorrência de cada caractere: (.)(?=.*\1)
Ou, usando este, eu posso fazer isso por duplicatas consecutivas, mas não por duplicatas: ([a-zA-Z1-9])\1{2,}
(.)(?<=^(?:(?:(?!\1).)*\1){2,}(?:(?!\1).)*\1)
regex. Demo .(.)(?<=(.*\1){3})
?(.)(?<=(?:.*\1){3})
também fará o trabalho, mas tudo isso não é bom, pois o retorno excessivo pode causar problemas com seqüências mais longas. Prefiro escrever um método que não seja regex para resolver o problema.(.)(?<=(?:.*\1){3})
25ms,(.)(?<=(?:\1.*?){2}\1)
3ms. Você pode apenas testar a si mesmo. O seu parece ser o padrão menos eficiente e mais difícil de ler.Respostas:
Solução não-regex R. Seqüência de caracteres dividida. Substitua os elementos deste vetor com rowid> = 3 * por
'-'
. Cole-o novamente.*
rowid(x)
é um vetor inteiro com cada elemento representando o número de vezes que o valor do elemento correspondente dex
foi realizado. Portanto, se o último elemento dex
é1
, e é a quarta vez1
que ocorrex
, o último elemento derowid(x)
é4
.fonte
Você pode fazer isso facilmente sem regex:
Veja o código em uso aqui
Resultado:
Como isso funciona:
for u in set(s)
obtém uma lista de caracteres únicos na string:{'c','a','b','y','1','z','x'}
for i in ...
loops sobre os índices que reunimos em 3.[i for i in range(len(s)) if s[i]==u][2:]
faz um loop sobre cada caractere na string e verifica se ele correspondeu
(da etapa 1.), em seguida, corta a matriz do segundo elemento até o final (descartando os dois primeiros elementos, se existirem)s[:i]+'-'+s[i+1:]
- concatenar a substring até o índice com-
e depois a substring após o índice, omitindo efetivamente o caractere original.fonte
Uma opção com
gsubfn
dados
fonte
Sem uma linha liner python regex:
Isso enumera através da sequência, contando as ocorrências do caractere atual por trás dele e colocando o caractere apenas se for um dos 2 primeiros, caso contrário, traço.
fonte
Outra maneira de fazer isso
pandas
.Saída :
fonte
Agradecimentos a Wiktor Stribiżew , Stefan Pochmann e bobble bubble . Para fins de conclusão, estou publicando possíveis
regex
soluções discutidas nos comentários;Isso só é possível com um regex que suporta uma largura infinita. Usando o módulo regex Python PyPi, podemos fazer o seguinte:
Snippet .
fonte