Dart: what's the fastest way to check if a particular character in a string is a digit?
Of course I can do this by comparing it to 10 digits or even using regular expressions, but I am looking for the fastest way.
Here's what I came up with now, does that sound reasonable?
int _zero = "0".codeUnits[0]; int _nine = "9".codeUnits[0]; bool isDigit(String s, int idx) => s.codeUnits[idx] >= _zero && s.codeUnits[idx] <= _nine;
I'm a little surprised that I didn't find this method in the standard library, I hope I just missed it.
source to share
Looks good to me if you are not using Unicode characters.
A similar attempt, but I would not expect this to be faster:
bool isDigit(String s, int idx) => "0".compareTo(s[idx]) <= 0 && "9".compareTo(s[idx]) >= 0;
It would be interesting if the compiler optimizes this duplicate s[idx]
/ s.codeUnits[idx]
, but I would expect it.
source to share
I did a quick micro test for various alternatives and it looks like it is almost a link between the Günter method and brute force testing. I prefer Gunther's method for elegance, but if performance is absolutely critical, it seems like brute force can win by a small margin. The test runs each method once for an index that will return true and once for an index that will return false.
Brute force method:
bool isDigit(String s, int idx) { return s[idx] == "0" || s[idx] == "1" || s[idx] == "2" || s[idx] == "3" || s[idx] == "4" || s[idx] == "5" || s[idx] == "6" || s[idx] == "7" || s[idx] == "8" || s[idx] == "9"; }
0.045421617878512024.
Gunther's method:
bool isDigit(String s, int idx) => "0".compareTo(s[idx]) <= 0 && "9".compareTo(s[idx]) >= 0;
0.054188391470161947 us
The way your code is:
int _zero = "0".codeUnits[0]; int _nine = "9".codeUnits[0]; bool isDigit(String s, int idx) => s.codeUnits[idx] >= _zero && s.codeUnits[idx] <= _nine;
0.6344102870896872 us
This can be improved with 2x by storing the results of s.codeUnits [idx] (for some reason the VM cannot optimize it, unlike other methods where repeated calls to s [idx] are optimized and no slower than storing the intermediate result ):
bool isDigit(String s, int idx) { int cuIdx = s.codeUnits[idx]; cuIdx >= _zero && cuIdx <= _nine; }
0.29245961607948817 us
Regex method:
RegExp digitRegExp = new RegExp(r'\d'); bool isDigit(String s, int idx) => s[idx].contains(digitRegExp);
4.812064808888846 us
int.parse method (extremely slow):
bool isDigit(String s, int idx) { bool isDigit = true; try { int.parse(s[2]); } catch (e) { isDigit = false; } return isDigit; }
102.48526774276198 us
source to share