title: JavaScript map a regex with multiple matches at the right occurrence
body: <p>I have an <code>array</code> of tokens to map, and a regex that gets the begin and end positions of each token within an input sentence. This works ok when the token has one occurrence. When the token has multiple occurrences, the greedy <code>Regex</code> will get all the matched positions of the token in the text, so the resulting position for the i-th token occurrence will be mapped by the last found position.</p>
  
  <p>By example, given the text </p>
  
  <pre><code>var text = "Steve down walks warily down the street down\nWith the brim pulled way down low";
  </code></pre>
  
  <p>the first occurrence of the token <code>down</code> is mapped to the last position in the text matched by the <code>RegExp</code>, hence I have:</p>
  
  <pre><code> {
      "index": 2,
      "word": "down",
      "characterOffsetBegin": 70,
      "characterOffsetEnd": 73
    }
  </code></pre>
  
  <p>This becomes clear running this example:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var text = "Steve down walks warily down the street down\nWith the brim pulled way down low";
  var tokens = text.split(/\s+/g);
  var annotations = tokens.map((word, tokenIndex) =&gt; { // for each token
    let item = {
      "index": (tokenIndex + 1),
      "word": word
    }
    var wordRegex = RegExp("\\b(" + word + ")\\b", "g");
    var match = null;
    while ((match = wordRegex.exec(text)) !== null) {
      var wordStart = match.index;
      var wordEnd = wordStart + word.length - 1;
      item.characterOffsetBegin = wordStart;
      item.characterOffsetEnd = wordEnd;
    }
    return item;
  });
  console.log(annotations)</code></pre>
  </div>
  </div>
  </p>
  
  <p>where the first occurrence of the token <code>down</code> should be the first matching position:</p>
  
  <pre><code> {
      "index": 2,
      "word": "down",
      "characterOffsetBegin": 6,
      "characterOffsetEnd": 9
    }
  </code></pre>
  
  <p>So given that I have mapped the tokens position for each occurrence of the token in the text i.e. first occurrence of <code>down</code> with the first match, the 2nd with the second match etc. I can reconstruct the text accordingly with the <code>charOffsetBegin</code> and <code>charOffsetEnd</code> hence doing like:</p>
  
  <pre><code>                var newtext = '';
                  results.sentences.forEach(sentence =&gt; {
                      sentence.tokens.forEach(token =&gt; {
                          newtext += text.substring(token.characterOffsetBegin, token.characterOffsetEnd + 1) + ' ';
                      });
                      newtext += '\n';
                  });
  </code></pre>