1

I am using an object as a hash table and I have stuffed both regular properties and integers as keys into it.

I am now interested in counting the number of keys in this object which are numbers, though obviously a for (x in obj) { if (typeof x === "number") { ... } } will not produce the result I want because all keys are strings.

Therefore I determined that it is sufficient for my purposes to assume that if a key's first character is a number then it must be a number so I am not concerned if key "3a" is "wrongly" determined to be a number.

Given this relaxation I think i can just check it like this

for (x in obj) {
  var charCode = x.charCodeAt(0);
  if (charCode < 58 && charCode > 47) { // ascii digits check
     ...
  }
}

thereby avoiding a regex and parseInt and such.

Will this work? charCodeAt is JS 1.2 so this should be bullet-proof, yes?

Hint: I would love to see a jsperf comparing my function with what everyone comes up with. :) I'd do it myself but jsperf confuses me

Update: Thanks for starting up the JSPerf, it confirms my hope that the charCodeAt function would be executing a very quick piece of code reading out the int value of a character. The other approaches involve parsing.

Steven Lu
  • 36,733
  • 50
  • 179
  • 328

4 Answers4

3

parseInt(x, 10) will correctly parse a leading positive or negative number from a string, so try this:

function startsWithNumber(x) {
    return !isNaN(parseInt(x, 10));
}

startsWithNumber('123abc'); // true
startsWithNumber('-123abc'); // true
startsWithNumber('123'); // true
startsWithNumber('-123'); // true
startsWithNumber(123); // true
startsWithNumber(-123); // true
startsWithNumber('abc'); // false
startsWithNumber('-abc'); // false
startsWithNumber('abc123'); // false
startsWithNumber('-abc123'); // false
Matt Ball
  • 332,322
  • 92
  • 617
  • 683
2

The question is misleading because it is hard to tell this of a variable's name but in the example you're dealing with object properties (which are some kind of variables of course...). In this case, if you only need to know if it starts with a number, probably the best choice is parseInt. It will return NaN for any string that doesn't start with a number.

marekful
  • 13,318
  • 5
  • 30
  • 52
  • Indeed `parseInt` would be a solid choice as well and likely similar in perf to `isNaN`, though it's clear that only the first character ever needs to be checked. – Steven Lu Jan 22 '13 at 21:19
2

Why speculate when you can measure. On Chrome, your method appears to be the fastest. The proposed alternatives all come at about 60% behind on my test runs.

jevakallio
  • 33,015
  • 3
  • 95
  • 111
  • Thanks! Not often you get to see 60M ops/s on JSPerf – Steven Lu Jan 22 '13 at 21:31
  • Wow! look at that bar for Firefox 18!! Something tells me the JIT is optimizing something out. – Steven Lu Jan 22 '13 at 21:36
  • @StevenLu, yeah, I had to also test for myself, got a very similar result. I'll see if I can change the test cases so that the JIT doesn't drop the code paths as redundant, which I presume is what is happening. – jevakallio Jan 22 '13 at 21:37
  • @StevenLu Once we gained our code in 65M times for Chrome and in 450M times for Firefox after answer in this question: http://stackoverflow.com/questions/14218363/detecting-if-anything-on-the-page-is-being-animated. – VisioN Jan 22 '13 at 21:48
  • @StevenLu either I don't know how to trick the firefox js compiler, or then firefox really is that fast on `charCodeAt`: http://jsperf.com/is-string-a-number/4 – jevakallio Jan 22 '13 at 21:54
  • It only really needs to dereference a pointer and spit back the char's int value. I'd expect it to be blisteringly fast. Question would be why is webkit so slow in comparison. – Steven Lu Jan 22 '13 at 22:21
  • @StevenLu Suprisingly (or not...) the `charCodeAt` isn't the fastest on IE9 - string comparison is, though not by much, and they're all slow compared to a real browser. – jevakallio Jan 22 '13 at 22:26
  • This is pretty good, my original proposition blows every other approach out of the water. Kinda miffed the question still has no upvotes. – Steven Lu Jan 23 '13 at 03:51
0

You could also use isNaN(x) or isFinite(x) - see this SO question

Community
  • 1
  • 1
Gereon
  • 14,827
  • 4
  • 36
  • 62
  • So the question is, are either of those better/faster than a (< 58 && > 47) check – Steven Lu Jan 22 '13 at 21:14
  • 2
    I would consider it better, because it won't break if sometime later you add the key "123foo" – Gereon Jan 22 '13 at 21:15
  • 1
    This has a different answer than the original solution, although perhaps a better one. `!isNan('3a') === false`, whereas `originalSolution('3a') === true`. – Scott Sauyet Jan 22 '13 at 21:16