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?