5
$\begingroup$

I've been looking for a way to read numbers that have thousands separators in them:

StringCases[" 1142.123 ",  Whitespace ~~ NumberString ~~ Whitespace, 1]

gives

{" 1142.123 "}

but

StringCases[" 1,142.123 ", Whitespace ~~ NumberString ~~ Whitespace, 1]

gives

{}

So ideally there's a Mathematica way of defining NumberString to recognize commas in numbers. Or should I be looking into regexen at this point?

$\endgroup$

4 Answers 4

6
$\begingroup$

This is admittedly a bit of a hack, but you could remove the commas first, using StringReplace:

StringCases[
 StringReplace[" 1,142.123 ", "," -> ""], 
 Whitespace ~~ NumberString ~~ Whitespace, 1]

(* ==> {" 1142.123 "} *)
$\endgroup$
1
  • $\begingroup$ This was the solution I used for another question, and as of yet, I don't see a way around it. $\endgroup$
    – rcollyer
    Commented May 3, 2012 at 14:02
13
$\begingroup$

I would just go to RegExp:

StringCases[" 1,142.123 ", RegularExpression["\\s[0-9,.]+\\s"], 1]

(* {" 1,142.123 "} *)

You could also go with:

ImportString[" 1,142.123 ","List"]

Though that will automatically change it to Numeric, which doesn't seem to be what you want...

$\endgroup$
6
  • 1
    $\begingroup$ +1 For anyone who understands regular expressions... $\endgroup$
    – Eli Lansey
    Commented May 3, 2012 at 14:15
  • $\begingroup$ I think you meant ImportString, so I fixed it. I had forgotten about that function, +1. $\endgroup$
    – rcollyer
    Commented May 3, 2012 at 14:17
  • $\begingroup$ ImportString does many tricks, but sometimes is too slow. Anyway it's a very good option if you don't want to build your own transformation. $\endgroup$
    – FJRA
    Commented May 3, 2012 at 14:18
  • $\begingroup$ @rcollyer oops, thanks. My MMA crashed for some reason, so I just typed from memory, but apparently had bad short-term memory $\endgroup$
    – tkott
    Commented May 3, 2012 at 14:19
  • $\begingroup$ @EliLansey this made everything crystal clear: regular-expressions.info (sort-of) :) $\endgroup$
    – tkott
    Commented May 3, 2012 at 14:20
5
$\begingroup$

Regular expressions are nice, but there is no need to use them here.

numString = (NumberString | ",") .. ;

StringCases[" 1,142.123 ", Whitespace ~~ numString ~~ Whitespace, 1]
{" 1,142.123 "}

The form above is admittedly not robust as a valid number string should not start or end with a comma or have two decimal points, and I believe the comma should not immediately precede a decimal point or appear to its right side. The easiest way I can think to preclude these is to check for them explicitly:

numString = x : (NumberString | ",") .. /;
   ! StringMatchQ[x, ",*" | "*," | "*.*,*" | "*,.*" | "*.*.*"];

StringCases[" 1,2. ,3 4, 5.6,7,.89 0.1.2sam, i am ", numString]
{"1,2.", "3", "4", "5.6", "7", ".89", "0.1", ".2"}
$\endgroup$
2
  • $\begingroup$ @R.M maybe I need to lern me my's RegEx, but I believe tkott's pattern is equivalent (besides whitespace) to my first form: (NumberString | ",") .. in which case I would argue that, in the context of Mathematica, his is clunky. (Incidentally I already voted for his answer.) $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2012 at 14:45
  • $\begingroup$ I don't know regex well either :P I would've written something like this had I seen this question then too. I assumed his regex was equivalent to the second half of your answer, but on looking closer, I see that's not the case. Including all the exceptions would make his just as clunky, so comment revoked! :) $\endgroup$
    – rm -rf
    Commented Aug 18, 2012 at 16:03
1
$\begingroup$

Fast forward 7 years...

The reason your code didn't work as desired is because the stock string pattern, NumberString, was lamed. It could handle decimal points OK but not block separators such as commas and spaces (no matter how thin).

And now, 7 years later, with 12 it is still lame.

So one way to solve your problem is to build a less lame NumberString, one that can interpret block separators, even very thick spaces:

lessLameNumberString = n__ /; NumberQ[ SemanticInterpretation[n] ]

Now substituting back into your original code

StringCases[" 1,142.123 ", Whitespace ~~ lessLameNumberString ~~ Whitespace, 1]

gives

{" 1,142.123 "}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.