Replace occurrences arbitrarily in Javascript

Asked

Viewed 132 times

1

I’m using the method replace() in order to highlight certain words in a sentence. The method replaces only the first occurrence of the target word by default. I’d like to know how make arbitrary substitutions. Ex: Replace the second indentation of the word in one case, replace the first and third, replace the second and third, 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 perform a normal replacement if the variable value ocr be it false, but if the value is 2, for example, only the 2nd occurrence should be replaced. I would also like, as I mentioned at the beginning, if possible, provide all occurrences at once, in the same variable. Example: var ocr = 2-3, (of course it may not be written like this! ), it would replace the second and third occurrences, and var ocr = 1,3, replace the 1st and 3rd occurrences. Preferably, the solution should use the method replace(), but I am open to other ideas. Thanks for your attention.

1 answer

2


I did the job replaceString which follows on the basis of the second code which is demonstrated in this section of this link.

To prove it works includes unit testing with Qunit, then just click on the button "Run code snippet" that is below to test.

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>
<script src="http://code.jquery.com/qunit/qunit-1.17.1.js"></script>
<div id="qunit"></div>
<div id="qunit-fixture"></div>

The function replaceString takes 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 substitutions. The fourth is an array containing the indexes in which the substitution will occur, where 1 is the first, 2 is the second, 3 is the third, etc. Invalid indexes in this array (0, negative, or too large) are ignored/forgiven. Repeated indexes are ignored/forgiven. Indexes do not need to be in order.

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

  • I really liked your solution! One last thing I would like is that if the last (fourth) parameter is not provided, a normal substitution occurs, since I will already know beforehand whether or not the target word is repeated within the sentence. Could you add more functionality, please?

  • @Eden Feito! :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.