Replace occurrences arbitrarily in JavaScript

1

I'm using the replace() method to highlight certain words in a sentence. The method replaces only the 1st occurrence of the target word by default. I would like to know how perform arbitrary overrides . Ex: Replace the 2nd sentence of the word in one case, in another substitute the 1st and 3rd occurrences, another the 2nd and 3rd, etc. Below, the sentence contains 3 occurrences of the word "above":

var stc = 'acima do limite da razão, acima da capacidade do cérebro, acima de tudo.'
var plv = 'acima'; // palavra-alvo
var rpl = new RegExp("\b" + plv + "\b");
var plv_subs = '<span class="myclass">acima</span>'; // palavra estilizada.
var ocr = 2; // ocorrência(s).

stc = stc.replace(rpl, plv_subs); // substituição normal.

The idea is to perform a 'normal' substitution, if the value of the variable ocr , but if the value is 2, for example, only the 2nd occurrence must be replaced. I would also like, as I mentioned earlier, if possible, provide all occurrences at once , in the same variable. Example: false , (of course it might not be written like this!), Would replace the 2nd and 3rd occurrences, and var ocr = 2-3 , would replace the 1st and 3rd occurrences. Preferably, the solution should use the var ocr = 1,3 method, but I am open to other ideas. Thanks in advance for your attention.

    
asked by anonymous 15.03.2015 / 03:17

1 answer

2

I made the following replaceString function based on the second code that is demonstrated in this section of this link .

To prove that it works include unit tests with QUnit , then just click on the "► Run code snippet "that is below for testing.

function replaceString(oldS, newS, fullS, ocr) {
  var temOcr = arguments.length >= 4;
  var parts = fullS.split(oldS);
  var substituicoes = [];
  for (var i = 0; i < parts.length - 1; i++) {
    substituicoes[i] = temOcr ? oldS : newS;
  }
  if (temOcr) {
    for (var e in ocr) {
      var idx = ocr[e] - 1;
      if (idx >= 0 && idx < substituicoes.length) substituicoes[idx] = newS;
    }
  }
  var result = parts[0];
  for (var i = 0; i < substituicoes.length; i++) {
    result += substituicoes[i] + parts[i + 1];
  }
  return result;
}

QUnit.test("Testa a função replaceString", function(assert) {
  var testando = 'acima do limite da razão, acima da capacidade do cérebro, acima de tudo.';
  var resultadoEsperado = '<span class="myclass">acima</span> do limite da razão, <span class="myclass">acima</span> da capacidade do cérebro, <span class="myclass">acima</span> de tudo.';
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [1, 2, 3]), resultadoEsperado, "Substitui todos os índices");
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando), resultadoEsperado, "Omitindo os índices");

  resultadoEsperado = '<span class="myclass">acima</span> do limite da razão, acima da capacidade do cérebro, <span class="myclass">acima</span> de tudo.';
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [1, 3]), resultadoEsperado, "Substitui alguns dos índices (1, 3)");
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [3, 1]), resultadoEsperado, "Substitui alguns dos índices, mesmo fora de ordem (1, 3)");
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [3, 3, 1, 1]), resultadoEsperado, "Substitui alguns dos índices, mesmo com repetição (1, 3)");

  resultadoEsperado = 'acima do limite da razão, <span class="myclass">acima</span> da capacidade do cérebro, <span class="myclass">acima</span> de tudo.';
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [2, 3]), resultadoEsperado, "Substitui alguns dos índices (2, 3)");

  resultadoEsperado = 'acima do limite da razão, <span class="myclass">acima</span> da capacidade do cérebro, acima de tudo.';
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [2]), resultadoEsperado, "Substitui um dos índices (2)");

  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, []), testando, "Não substitui nada");
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [4]), testando, "Tenta substituir além da última ocorrência");
  assert.equal(replaceString('abacaxi', 'banana', testando, []), testando, "Não substitui nada por algo que não existe na frase");
  assert.equal(replaceString('abacaxi', 'banana', testando, [1, 2, 3, 4, 5]), testando, "Tenta substituir por algo que não existe na frase");
  assert.equal(replaceString('acima', '<span class="myclass">acima</span>', testando, [-4, 7, 2, 0, 2, -2]), resultadoEsperado, "Tenta substituir com índices inválidos (2)");
  
  assert.equal(replaceString('arara', 'papagaio', 'zarararararaz', [1, 2]), 'zpapagaiorpapagaioz', "Verifica se ocorrências não se sobrepõem (1, 2)");
  assert.equal(replaceString('arara', 'papagaio', 'zarararararaz', [2]), 'zarararpapagaioz', "Verifica se ocorrências não se sobrepõem (2)");

  assert.equal(replaceString('ana', 'banana', 'ana e mariana gostam de banana', [1, 2, 3, 4]), 'banana e maribanana gostam de bbananana', "Verifica se funciona quando o substituído é parte do substituto");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><scriptsrc="http://code.jquery.com/qunit/qunit-1.17.1.js"></script>
<div id="qunit"></div>
<div id="qunit-fixture"></div>

The replaceString function receives four parameters. The first is the string you want to replace. The second is the substitute string. The third is the complete string in which there will be the substitutions. The fourth is an array containing the indices where the substitution occurs, where 1 is the first, 2 the second, 3 the third, and so on. Invalid indices in this array (0, negative, or too large) are ignored / pardoned. Repeated indexes are ignored / forgiven. The indexes need not be in order.

You can check in the snippet tests above, that various situations are tested, and in all of them, the code works as expected.

    
15.03.2015 / 08:48