views:

105

answers:

5

I have a string of digits, ex: "1234", and I need to return the largest matched group of digits for each number in a comma-separated list.

Searching for "1234" in "1000, 1200, 1330, 1235" would return

["1", "12", "1", "123"]

Thanks!

A: 

This doesn't feel like a problem regexes can solve.

Ned Batchelder
+2  A: 

This strikes me as something that is best done by writing a custom string parser, not by using regexes. So for instance,

function maxMatch(num) {
    var s = num.toString();
    var max = 0;
    var n = 0;
    for (var i = 0; i < s.length(); i++) {
        if (s[i] == n) {
            ++n;
        }
        else if (s[i] == '1') {
            n = '2';
        }
        else if (n != 0) {
            max = parseInt(n) > max ? parseInt(n) : max;
            n = 0;
        }
    }
    return max;
}

My Javascript is rusty (and this is untested) but something kind of like that should work, and could form part of your solution.

David Zaslavsky
+3  A: 

Yeah, like Ned said, its really not a good problem for regexes ... but ... I think it can be brute forced with something like:

'(1(2(34?)?)?)[^,]*,'

Basically what I'm doing here is looking for 1 optionally followed by (2 optionally followed by ...) followed by (anything not a comma to eat up the rest of the number).

But, really, please don't try to do it this way :-)

You actually have 1 more set of parens than is necessary - `(1(2(34?)?)?)[^,]*` would work fine since the `?` operator is tight-binding to a single character.
Amber
Good point. Missed that.
A: 

Another way to do it with regex:

(?<=\s|^)(1234|123|12|1)

Of course, like others have mentioned I'd lean away from a regex solution in this particular scenario if possible. If you can actually parse and cast each number to a numeric type this would be more flexible, I'd think.

Steve Wortham
JavaScript regexes don't support lookbehinds, but `\b` would have the same effect (assuming the comma-separated strings will never contain letters or underscores).
Alan Moore
A: 
String.prototype.matchChars= function(str){
    var s= this, i= 0, L= this.length, tem= '';
    while(i< L){
     if(this[i]!= str[i]) return tem;
     tem+= this[i];
     i+= 1;
    }
    return tem;
}

function matchcharsinList(s, A){
    if(typeof A== 'string') A= A.split(/, */);
    for(var j= 0, n= A.length; j<n; j++){
     tem= A[j] || '';
     A[j]= s.matchChars(tem);
    }
    return A;
}

alert(matchcharsinList('1234','1000, 1200, 1330, 1235'));

/*
A more useful method might allow case insensitive matches,, and a minimum length of a match:

*/
String.prototype.matchChars= function(str, min, ignorecase){
    var s= this, i= 0, L= this.length, tem= '';
    if(ignorecase){
     s= s.toLowerCase();
     str= str.toLowerCase();
    }
    if(min && str.substring(0, min)!= s.substring(0, min)) return '';
    while(i< L){
     if(this[i]!= str[i]) return tem;
     tem+= this[i];
     i+= 1;
    }
    return tem;
}
kennebec