Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

106
Visualizações
Replace string with multiple values, without interference

Say, I have a string to be replaced:

let searches = ['gone', 'go', 'run']
let s = 'go went gone-go'
const lookup = {
  'go': '(go)',
  'gone': '[gone]',
}

for (let key of searches) {
    s = s.replaceAll(key, lookup[key])
}

console.log(s)

And I get (go) went [(go)ne]-(go). Assume s can be any string with some words from lookup keys, and lookup values won't necessarily have consistent patterns. searches is the variable from outside inputs.

If I change orders in searches to, for example, ['go', 'gone', 'run'], result becomes (go) went (go)ne-(go).

The result I'm expecting is (go) went [gone]-(go), so that longer ones are replaced first, and won't be replaced by later matches.

I did come up with a solution that replacing values from lookup to uuid first, iterating from longer keys to shorter ones, then replace uuid back with corresponding values. Of course, this is rather stupid and inefficient:

let searches = ['go', 'gone', 'run']
let s = 'go went gone-go'
const lookup = {
  'go': '(go)',
  'gone': '[gone]',
}

const uuid = () => Date.now().toString(36) + Math.random().toString(36).substring(2)  // pseudo uuid for quick demo. src: https://stackoverflow.com/a/44078785/17954892
let uuidKeys = {}
Object.keys(lookup).forEach(k => uuidKeys[k] = uuid())  // uuidKeys = {'go': 'random1', 'gone': 'random2'}
let uuids = Object.values(uuidKeys)  // uuids = ['random1', 'random2']
let uuidValues = {}
Object.keys(lookup).forEach((k, i) => uuidValues[uuids[i]] = lookup[k])  // uuidValues = {'random1': '(go)', 'random2': '[gone]'}
searches.sort((a, b) => b.length -a.length)  // searches = ['gone', 'run', 'go']
for (let key of searches) {
    s = s.replaceAll(key, uuidKeys[key])  // s = 'random1 went random2-random1'
}
for (let key of searches.map(i => uuidKeys[i])) {
    s = s.replaceAll(key, uuidValues[key])  // s = '(go) went [gone]-(go)'
}

console.log(s)

I then thought about loop-split the string by searches, then replace and record the index that's processed, and finally join the list back to string. However, I cannot find a nice way to implement it without expensive Array methods (flat, splice, etc.) in for-loops.

Is there an elegant/efficient way to achieve the result?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

You can do this by using a regular expression with the g flag with replace, passing a callback function as the replacement; the function then picks the appropriate replacement based on what matched.

For instance:

let searches = ["gone", "go", "run"];
let s = "go went gone-go";
const lookup = {
    "go": "(go)",
    "gone": "[gone]",
};
let rex = new RegExp(searches.map(escapeRegex).join("|"), "g");
s = s.replace(rex, match => lookup[match]);
console.log(s);

...where escapeRegex escapes any charactesr in the search strings that have special meaning in regular expressions; see this question's answers for possible implementations.

Live Example:

function escapeRegex(string) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

let searches = ["gone", "go", "run"];
let s = "go went gone-go";
const lookup = {
    "go": "(go)",
    "gone": "[gone]",
};
let rex = new RegExp(searches.map(escapeRegex).join("|"), "g");
s = s.replace(rex, match => lookup[match]);
console.log(s); // "(go) went [gone]-(go)"

Note: The order of the strings in the searches array matters. If you put "go" before "gone", it'll match first:

function escapeRegex(string) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

let searches = ["go", "gone", "run"];
// Note −−−−−−−−^
let s = "go went gone-go";
const lookup = {
    "go": "(go)",
    "gone": "[gone]",
};
let rex = new RegExp(searches.map(escapeRegex).join("|"), "g");
s = s.replace(rex, match => lookup[match]);
console.log(s); // "(go) went (go)ne-(go)"

If you always want the longest one to have the highest precedence, and you can't control the contents of the input array, you could sort it prior to using it:

function escapeRegex(string) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

let searches = ["go", "gone", "run"];
// Note −−−−−−−−^
let s = "go went gone-go";
const lookup = {
    "go": "(go)",
    "gone": "[gone]",
};
let rex = new RegExp(
    searches.sort((a, b) => b.length - a.length)
      .map(escapeRegex)
      .join("|"),
    "g"
);
s = s.replace(rex, match => lookup[match]);
console.log(s); // "(go) went [gone]-(go)"

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda