Having the following array of objects:
const variables = [
{ name: '%NAME%', value: 'joe' },
{ name: '%EMAIL%', value: '%NAME%@mail.com' },
{ name: '%HOBBY%', value: 'tennis' }
];
And the input string:
const inputString = `Hi, my name is %NAME%, I like %HOBBY%, you can contact me at %EMAIL%`;
The function should take as arguments variables and inputString and return the following sting:
'Hi, my name is joe, I like tennis, you can contact me at joe@mail.com'
Here is the function so far:
function doMagic(variables, inputString) {
let output = inputString;
for (let i = 0; i < variables.length; i++) {
output = inputString.replace(variables[i].name, variables[i].value);
}
return output;
}
Unfortunatelly, this only finds one occurrence, in case there are more, and it doesn't go into nested variables, like %EMAIL%.
Any ideas to improve?
We can do a regex replacement with the help of a callback function:
var variables = [
{name: '%NAME%', value: 'joe'},
{name: '%EMAIL%', value: 'joe@mail.com'},
{name: '%HOBBY%', value: 'tennis'}
];
var regex = new RegExp("(" + variables.map(x => x.name).join("|") + ")", "g");
var inputString = "Hi, my name is %NAME%, I like %HOBBY%, you can contact me at %EMAIL%";
var output = inputString.replace(regex, (m) => {
return variables.filter(x => x.name == m)[0].value;
});
console.log(output);
The strategy here is to first build a regex alternation of names from the map. We do a global regex search for these names in the input string. For each match, the callback function replaces the name with the value from the map.
Looping backwards through the array, and using replaceAll() should do the trick.
const variables = [
{ name: '%NAME%', value: 'joe' },
{ name: '%EMAIL%', value: '%NAME%@mail.com' },
{ name: '%HOBBY%', value: 'tennis' },
];
const inputString = `Hi, my name is %NAME%', I like %HOBBY%, you can contact me at %EMAIL%`;
function doMagic(variables, inputString) {
let output = inputString;
variables.slice().reverse().forEach(variable => {
output = output.replaceAll(variable.name, variable.value);
})
return output;
}
console.log(doMagic(variables, inputString));
Using regex and while(regex.test.output()) also does the trick.
const variables = [
{ name: '%NAME%', value: 'joe' },
{ name: '%EMAIL%', value: '%NAME%@mail.com' },
{ name: '%HOBBY%', value: 'tennis' },
];
const inputString = `Hi, my name is %NAME%', I like %HOBBY%, you can contact me at %EMAIL%`;
function doMagic(variables, inputString) {
const regex = new RegExp("(" + variables.map(x => x.name).join("|") + ")", "g");
let output = inputString;
while (regex.test(output)) {
output = output.replace(regex, m => {
return variables.filter(x => x.name == m)[0].value;
})
}
return output;
}
console.log(doMagic(variables, inputString));
You could do a recursive call until there are no variables left in the string
const variables = [
{ name: '%NAME%', value: 'joe' },
{ name: '%EMAIL%', value: '%NAME%@mail.com' },
{ name: '%HOBBY%', value: 'tennis' },
];
const inputString = `Hi, my name is %NAME%', I like %HOBBY%, you can contact me at %EMAIL%`;
function doMagic(variables, inputString) {
let output = inputString;
for (let i = 0; i < variables.length; i++) {
output = output.replace(variables[i].name, variables[i].value);
}
for (let i = 0; i < variables.length; i++) {
if (output.includes(variables[i].name)) {
output = doMagic(variables, output);
}
}
return output;
}
console.log(doMagic(variables, inputString));