Je recherche un regex
motif qui correspondra à la troisième, quatrième, ... occurrence de chaque caractère. Regardez ci-dessous pour des éclaircissements:
Par exemple, j'ai la chaîne suivante:
111aabbccxccybbzaa1
Je veux remplacer tous les caractères dupliqués après la deuxième occurrence. La sortie sera:
11-aabbccx--y--z---
Quelques modèles d'expression régulière que j'ai essayés jusqu'à présent:
En utilisant l'expression régulière suivante, je peux trouver la dernière occurrence de chaque caractère: (.)(?=.*\1)
Ou en utilisant celui-ci, je peux le faire pour les doublons consécutifs mais pas pour les doublons: ([a-zA-Z1-9])\1{2,}
(.)(?<=^(?:(?:(?!\1).)*\1){2,}(?:(?!\1).)*\1)
regex. Démo .(.)(?<=(.*\1){3})
?(.)(?<=(?:.*\1){3})
cela fera aussi l'affaire, mais tout cela n'est pas bon car un retour en arrière excessif peut causer des problèmes avec des chaînes plus longues. Je préfère écrire une méthode non regex pour résoudre le problème.(.)(?<=(?:.*\1){3})
ms, 3(.)(?<=(?:\1.*?){2}\1)
ms. Vous pouvez simplement vous tester. Le vôtre semble être le modèle le moins efficace et il est le plus difficile à lire.Réponses:
Solution non regex R. Chaîne fendue. Remplacez les éléments de ce vecteur ayant rowid> = 3 * par
'-'
. Collez-le ensemble.*
rowid(x)
est un vecteur entier dont chaque élément représente le nombre de fois où la valeur de l'élément correspondant dex
a été réalisée. Donc, si le dernier élément dex
est1
, et c'est la quatrième fois que cela1
se produitx
, le dernier élément derowid(x)
est4
.la source
Vous pouvez facilement accomplir cela sans regex:
Voir le code utilisé ici
Résultat:
Comment cela fonctionne:
for u in set(s)
obtient une liste de caractères uniques dans la chaîne:{'c','a','b','y','1','z','x'}
for i in ...
boucle sur les indices que nous rassemblons en 3.[i for i in range(len(s)) if s[i]==u][2:]
boucle sur chaque caractère de la chaîne et vérifie s'il correspondu
(à partir de l'étape 1.), puis il tranche le tableau du 2e élément à la fin (en supprimant les deux premiers éléments s'ils existent)s[:i]+'-'+s[i+1:]
- concaténer la sous-chaîne jusqu'à l'index avec-
, puis la sous-chaîne après l'index, en omettant effectivement le caractère d'origine.la source
Une option avec
gsubfn
Les données
la source
Pas de doublure en python regex:
Cela énumère à travers la chaîne, en comptant les occurrences du caractère actuel derrière lui et en ne mettant le caractère que s'il est l'un des 2 premiers, sinon tiret.
la source
Une autre façon de le faire avec
pandas
.Sortie :
la source
Merci à Wiktor Stribiżew , Stefan Pochmann et bobble bubble . Par souci d’achèvement, je publie les
regex
solutions possibles discutées dans les commentaires;Cela n'est possible qu'avec un regex qui prend en charge la recherche de largeur infinie. En utilisant le module regex Python PyPi, nous pouvons effectuer les opérations suivantes:
Extrait .
la source