LJ Wadowski
LJ Wadowski

Reputation: 6720

Effective solution for create array containing all groups in regex matches

I am looking for an effective way to create array contain all matches contains regex groups matches.

e.g. Regex /(1)(2)(3)/g string 123 expected result ['1','2','3']

My current code looks like this:

    var matches = [];

    value.replace(fPattern, function (a, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15) {
        for(var i = 1, v; i < 15; i++){
            v = eval('s' + i);
            if(v){
                matches.push(v);       
            }else{
                break;
            }                
        }
    });

It works, however I don't like the way how it does.

The first thing is that I actually don't know how many groups I will have in my regex variable fPattern so I need to define a lot unnecessary variables s1, s2 ... etc.

The second problem Is that I decided to use evil eval to prevent pushing this variables 'manually' one by one to array, maybe there is a better solution?

And one more thing - I did try use match() but unfortunately when I have pattern /(1)(2)(3)/g it will return me array ['123'] so it's not what I want to achieve.

Thanks!

EDIT

Ok I found something which looks better

    matches = fPattern.exec(value);        
    if(matches && matches.length){
        for(var key in matches){                                
            if(key !== '0'){
                if(key !== 'index'){
                    formated += matches[key] + ' ';       
                }else{
                    break;
                }                    
            }                
        };
    }

Upvotes: 0

Views: 54

Answers (3)

markthethomas
markthethomas

Reputation: 4431

A less stateful / more functional solution might be something like this:

function findInString(string, pattern) {
   return string.split('').filter(function (element) {
      return element.match(pattern)
   })
}

Takes in a string to search through and regex literal, returns an array of the matched elements. So, for example:

var foo = '123asfasff111f6';

findInString(foo, /\d/g)

will return [ '1', '2', '3', '1', '1', '1', '6' ], which seems to be what you're looking for(?).(at least, based on the below)

e.g. Regex /(1)(2)(3)/g string 123 expected result ['1','2','3']

You can pass in whatever regex literal you want and it should act on every item in the array and return it if matched. I'd go with something like this if you want to easily be able to reason about state/might have to re-use it later to match a different pattern. The question was a little fuzzy for me, so your exact needs might be slightly different -- tried to go off what your expected inputs and outputs were.

Upvotes: 1

nhahtdh
nhahtdh

Reputation: 56809

Use RegExp.exec and collect its return values, which consist of the main match, the capturing groups and the starting index of the main match.

function findall(re, input) {
    // Match only once for non global regex
    // You are free to modify the code to turn on the global flag
    // and turn it off before return
    if (!re.global) {
        return input.match(re);
    } else {
        re.lastIndex = 0;
    }

    var arr;
    var out = [];

    while ((arr = re.exec(input)) != null) {
        delete arr.input; // Don't need this
        out.push(arr);

        // Empty string match. Need to advance lastIndex
        if (arr[0].length == 0) {
            re.lastIndex++;
        }
    }

    return out;
}

Upvotes: 1

nu11p01n73R
nu11p01n73R

Reputation: 26667

Something like

arrays = "123".match(/(1)(2)(3)/);
arrays.splice(0,1);
console.log(arrays);
=> Array [ "1", "2", "3" ]

The match returns an array where the array index 0 will contain the entire match. From array index 1 onwards it will contain the value of corresponding capture group.

arrays.splice(0,1);

would remove the index 0 element, the entire match from the array, The resulting array will only contain teh capture group values

Upvotes: 1

Related Questions