views:

78

answers:

2

I was using javascript to detect for specific key strokes and while writing the method I thought I'd try regular expressions and the test() method and came up with:

if (/8|9|37|38|46|47|48|49|50|51|52|53|54|55|56|57|96|97|98|99|100|101|102|103|104|105|110/.test(num)) {
    // do something if there's a match
}

This doesn't seem to work 100% as some values seem to make it past the regex test, such as 83. I've since moved on, but I'm still curious as to why this didn't work.

+6  A: 

This is the completely wrong way to do it.

To answer the question, the regex is matching part of your string. The string 83 passes by matching the 8.
You need to anchor your regex by putting ^( at the beginning and )$ at the end.

The correct way to do this is to make an array of valid numbers, and compare using parseInt.

For example:

var validNumbers = [ 8, 9, 37, 38, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 110 ];

if (validNumbers.indexOf(parseInt(num, 10)) >=0 ) {
    //Match
}

You'll need an indexOf function for IE:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(needle) {
        for(var i = 0; i < this.length; i++) {
            if(this[i] === needle) {
                return i;
            }
        }
        return -1;
    };
}
SLaks
Thanks for clearing up the regex problem and introducing me to prototype. Why is this completely the wrong way to do this? Performance? Readability? Maintainability? The example was detecting key codes, what if it had been searching for an instance of a string? Would test() be appropriate in that case or just use search().
ren33
+2  A: 

You need to specify the start and end of the string. Otherwise 8 in 8|… will match the 8 in 83:

/^(8|9|37|38|46|47|48|49|50|51|52|53|54|55|56|57|96|97|98|99|100|101|102|103|104|105|110)$/.test(num)

But you should rather use numeric comparison. If you don’t like to list every number, you can use ranges like this:

function foo(number, numbers) {
    for (var i=0; i<numbers.length; ++i) {
        if (numbers[i] === number) {
            return true;
        } else if (numbers[i].constructor === Array) {
            if (numbers[i][0] <= number && number <= numbers[i][1]) {
                return true;
            }
        }
    }
    return false;
}
var numbers = [8, 9, 37, 38, [46, 57], [96, 105], 110];
if (foo(num, numbers)) {
    // …
}
Gumbo