J'ai du mal à trouver une expression régulière qui supprime les caractères dupliqués dans une chaîne (c'est-à-dire ne garde que la première occurrence)
En particulier, je veux supprimer tous les deux-points après la première apparition
str_remove(string = s, pattern = "(:)(?=.*\1)") # [1] "note: conducted by j:m" "location: made :n :apan" "date: 2010, ma: 3rd"
4 Réponses :
Essayez d'utiliser sub
en deux étapes ici:
s <- c("note: conducted by j:m", "location: made in :apan", "date: 2010, ma: 3rd")
Données:
first <- sub("^(.*?:).*", "\\1", s) second <- sub("^.*?:", "", s) second <- sub(":", "", second, fixed=TRUE) out <- paste0(first, second) out [1] "note: conducted by jm" "location: made in apan" "date: 2010, ma 3rd"
L'approche ici consiste à capturer chaque chaîne jusqu'au premier deux-points inclus dans une variable, puis à capturer le reste de chaque chaîne dans une deuxième variable. Ensuite, nous supprimons les deux-points uniquement de la deuxième variable, et enfin nous collons les deux éléments ensemble pour générer la sortie attendue.
Notez qu'une manière plus concise de le faire serait d'utiliser sub ou peut-être
str_replace_all
avec une fonction de rappel, mais la syntaxe n'est pas si simple.
à la recherche d'une façon plus concise de faire cela, c'est-à-dire une regex simple ... sur certaines lignes j'ai plus de deux :
et je cours sur des dizaines de milliers de lignes, donc en créant des objets intermédiaires je suis inquiet de la vitesse - peut-être inutilement?
Comme je l'ai mentionné dans ma réponse, vous pourriez trouver un moyen de remplacer l'expression régulière en utilisant une ligne unique avec une fonction de rappel. Mais , même cela ne serait pas nécessairement plus efficace que la solution dans ma réponse.
Vu le problème posé, les expressions régulières semblent être un moyen trop compliqué de faire cela. Un moyen non-regex n'est-il pas beaucoup plus simple? Comme celui-ci:
for s in ss: it = re.subn( ":", "#", s, count=1 ) #Replace the first ":" with "#" to distinguish it from others print( it[0].replace( ":", "" ).replace( "#", ":" ) ) #Remove remaining ":"s and bring back the original
Bien sûr, si vous préférez une solution basée sur les regex pour une autre raison, cela ne fonctionnera pas. (De plus, la solution donnée est en Python et non en R, vous l'avez peut-être remarqué.)
@TimBiegeleisen Bon point. Si la nature des données d'entrée est connue, nous pouvons choisir un ou plusieurs caractères en conséquence. Par exemple, si je sais que # $ # $ ^ & ^ # $
ne viendra jamais dans la chaîne d'entrée, je peux choisir cela au lieu de #
.
Malheureusement, " Les correspondances de modèle Look-Behind doivent avoir une longueur maximale limitée. "
Donc, L'approche de Tim est probablement la voie à suivre
:
de la deuxième partie, et Voici une implémentation en une seule ligne:
s <- c("note: conducted by j:m", "location: made :n :apan", "date: 2010, ma: 3rd", "no double colon", "test1::::", "test2: colon1: colon2: end")
qui renvoie
[1] "note: conducted by jm" "location: made n apan" "date: 2010, ma 3rd" [4] "no double colon" "test1:" "test2: colon1 colon2 end"
pour un exemple de vecteur de caractères amélioré (y compris quelques cas de contour):
library(stringr) sapply(str_split(s, "(?<=:)", n = 2L), function(x) paste0(x[1L], str_remove_all(x[-1L], ":")))
Essayez ce modèle:
str = "location: made : in japan: or what:" str.gsub(/(?:^[^:]*:|\G(?!^))[^:]*\K:/, '')
Maintenant, ce que je ne sais pas, si cela serait applicable à Ruby car je ne sais presque rien à ce sujet pour être honnête.
J'ai eu cet exemple pour travailler sur une seule chaîne me laissant penser qu'il devrait fonctionner =)
(?:^[^:]*:|\G(?!^))[^:]*\K:
parfait ... fonctionne avec gsub (x = s, pattern = "(?: ^ [^:] *: | \\ G (?! ^)) [^:] * \\ K:", remplacement = "", perl = TRUE)