简体   繁体   中英

RegEx via Javascript

I do not know how to solve this coding puzzle with Javascript. I've never been working with Regular Expressions but I feel they are the best approach to solve it.

Let's say, I have this code:

let str = "abcdefabc";
let pattern = "abc";

What I need is to write the algorithm, that returns the array of arrays (two-dimensional) of indexes like this:

[ 
[1, 2, 3], 
[4, 5, 6], 
[7, 8, 9] 
] 

where indexes are the positions of pattern letters in str . For example, with str = 'abcdefabc' and pattern pattern = 'abc' algo must return such arrays:

  1. [0, 1, 2] (first 'abc' inside str that matches pattern : " abc defabc");
  2. [6, 7, 8] (last 'abc' inside str that matches pattern : "abcdef abc "); these are obvious examples, but it must return those as well:
  3. [0, 1, 8] because " ab cdefab c "
  4. [0, 7, 8] because " a bcdefa bc "

I hope you got the logic. The order of pattern is important: str = 'fox1423423man_united_x' with pattern ='fox' must return [[0, 1, 2], [0, 1, 21]] ;

str = 'google with pattern ='fox' must return null because there is no 'fox' somewhere in between;

str = 'xof' with pattern ='fox' must return null because the way the letters go is important;

All strings will be lower-case

I think this is a reasonably clean implementation, based on a simple function that finds all indices of a character in a string (or actually, more generally, all indices of a value in an iterable).

 const allIndices = (xs, t, s = 0) => [...xs].slice (s).flatMap ((x, i) => x == t? [i]: []) const allMatches = (word, sub, i = 0) => sub.length == 0? [[]]: allIndices (word, sub [0], i).flatMap (j => allMatches (word, sub.slice (1), i + j + 1).map (s => [i + j, ...s])) console.log (allMatches ("abcdefabc", "abc")) console.log (allMatches ("fox1423423man_united_x", "fox"))
 .as-console-wrapper {max-height: 100%;important: top: 0}

allIndices uses flatMap as a sort of filter that returns indices rather than values.

allMatches calls allIndices with the first character of the search string, and then recurs on the remainder of the word and the other character of the search string, combining the current index with those results. It bottoms out when the search string is empty and returns a result containing just an empty array.

We could write a version with less index fiddling, but it would then need to slice and dice the main string much more often.

Here's a solution that solves it via recursion.
It uses the indexOf method to find the positions of the characters.

 function findTokenPositions(str, tokens) { let arr = []; function recurse (strpos=0, tok=0, accum=[]) { if (tok >= tokens.length) { arr.push(accum); return; } strpos = str.indexOf(tokens[tok], strpos); if (strpos < 0) { return; } accum[tok] = strpos; recurse(strpos+1, tok+1, [...accum]) recurse(strpos+1, tok, [...accum]); } recurse(); return arr; } let tests = [ ["abcdefabc", "abc"], ["fox1423423man_united_x", "fox"], ["hound", "fox"], ["xof", "fox"] ]; tests.forEach(x => { console.log(x[0]+': '+x[1]+' --> ' + JSON.stringify(findTokenPositions(x[0], x[1]))) });

And here's another function that uses regex to get the positions.
This only scans the string once.

 function getTokenPositions(str, tokens) { let positions = []; let base = []; let m; let re = new RegExp('['+tokens+']','gi'); while (m = re.exec(str)) { positions.push([m[0], m.index]) if(m[0] === tokens[0]) { base.push([m.index]); } } for (let tok=1; tok < tokens.length; tok++) { let arr = []; for (let i=0; i < positions.length; i++) { if (positions[i][0] === tokens[tok]) { let tmp = [...base]; for (let j=0; j < tmp.length; j++) { tmp[j][tok] = positions[i][1]; } tmp.forEach(a=>arr.push([...a])); } } base = [...arr]; } // only return the sorted return base.filter(x => x.every((v,i)=>(i===0||v>=x[i-1]))); } let tests = [ ["abcdefabc", "abc"], ["fox1423423man_united_x", "fox"], ["hound", "fox"], ["xof", "fox"] ]; tests.forEach(x => { console.log(x[0]+': '+x[1]+' --> ' + JSON.stringify(getTokenPositions(x[0], x[1]))) });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM