8
votes

Ruby (sur rails) Regex: enlever des milliers de virgule de chiffres

Cela semble être un simple, mais il me manque quelque chose.

J'ai un certain nombre d'entrées provenant d'une variété de sources et de formats différents. p>

entrées numériques P>

123
123.45
123,45 (note the comma used here to denote decimals)
1,234
1,234.56
12,345.67
12,345,67 (note the comma used here to denote decimals)
  • Les numéros seront toujours inférieurs à 1 million li>
  • EDIT: Ce sont des prix, de sorte que ce soit des entiers entiers ou aller à la place des centièmes li> ul>

    J'essaie d'écrire une regex et d'utiliser GSub pour dépasser les milliers de virgules. Comment puis-je faire cela? P>

    J'ai écrit une regex: myregex = / \ d + (,) \ d {3} / code> p>

    quand je le teste Dans Rubular, il montre qu'il ne capture que la virgule que dans les cas de test que je veux. p>

    mais quand j'exécute gsub, je reçois une chaîne vide: INPUTR.GSUB (myregex, "") Code> P>

    On dirait que GSUB capture tout, pas seulement la virgule in (). Où suis-je mal? P> p>


3 commentaires

Pas possible si vous avez des sources différentes. Vous ne pouvez pas différencier si . dans 123.456 est mille séparateur ou point décimal. Vous devez extraire le contexte avant de faire le retrait.


@nhahtdh - Mes excuses, j'ai modifié pour ajouter que ce sont des prix, ce qui laisse quelques limites sur la largeur des intrants.


12,345,67 <- Quel pays utilise celui-ci de toute façon?


3 Réponses :


9
votes
result = inputstr.gsub(/,(?=\d{3}\b)/, '')
removes commas only if exactly three digits follow.(?=...) is a lookahead assertion: It needs to be possible to be matched at the current position, but it's not becoming part of the text that is actually matched (and subsequently replaced).

2 commentaires

C'était très serviable pour moi. Je devais la mettre en œuvre dans R, afin que quiconque ait besoin de faire la même chose, voici la version r: gsub (", (? = \\ d {3} \\ b)" "," , perl = true)


Si vous aviez la chaîne "ABC, 123", vous correspondez également à cette expression régulière. Y a-t-il une raison d'éviter de spécifier des chiffres avant la virgule?



1
votes

Vous êtes confondre "Match" avec "Capture": "Capture" signifie sauver quelque chose afin que vous puissiez y référer plus tard. Vous souhaitez capturer non pas la virgule, mais tout le reste, puis utiliser les portions capturées pour créer votre chaîne de substitution.

Essayez P>

myregex = /(\d+),(\d{3})/

inputstr.gsub(myregex,'\1\2')


4 commentaires

Cela échouera dès qu'il y a plus d'une virgule à remplacer: 1 000 000,00 deviendra 1000 000,00 .


O.P. est au courant - il a écrit: "[Les chiffres seront toujours inférieurs à 1 million]". Donc, je lui montrais comment faire de son travail réégien, plutôt que de créer un nouveau pour lui.


@theglauber - merci pour cela. C'est une bonne solution simple pour ce problème aussi. J'ai sélectionné une affirmation de regard sur la lunette, car elle est susceptible d'être plus robuste, par ex. Plus de 2 groupements sont nécessaires pour une raison quelconque.


Oh oui, la solution de Tim Pietzkler avec la lookahead Assertion est meilleure. Vous devriez être capable de généraliser une solution avec des captures également («Il y a plus d'une façon de le faire»). Mais je choisirais cette solution aussi.



0
votes

Dans votre exemple, il est possible à raconter du nombre de chiffres après le dernier séparateur (, ou . ) est un point décimal, puisqu'il y a 2 chiffres solitaires. Pour la plupart des cas , si le dernier groupe de chiffres n'a pas de 3 chiffres, vous pouvez supposer que le séparateur à l'avant est un point décimal. Un autre signe est l'apparence multiple d'un séparateur en grand nombre nous permet de différencier entre point décimal et séparateurs.

Cependant, je peux donner une chaîne 123,456 ou 123.456 sans sorte de contexte. Il est impossible dire s'il s'agit de "123 mille 456" ou de "123 points 456".

Vous devez numériser le document pour rechercher indice si , est utilisé pour mille séparateur ou point décimal, et inversement pour . . Avec le contexte fourni, vous pouvez alors appliquer la même méthode pour éliminer les milliers de séparateurs.

Vous pouvez également consulter Cet article sur Wikipedia sur les manières moins courantes de spécifier séparateurs ou points décimaux. Sachant et décider de ne pas soutenir est mieux que de supposer que les choses fonctionnent.


4 commentaires

Les données semblent être des prix cependant. Les prix n'auront jamais 3 décimales.


@Pguardiario: Le fait que ce soit le prix ajoute au contexte afin que l'on puisse en prendre une hypothèse. Il n'y a aucun moyen pour moi de deviner que c'est le prix.


Ah bon? Je n'avais aucun problème à deviner que :)


@nhahtdh - à nouveau excuses. Voir le commentaire et modifier ci-dessus concernant les prix.