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 [email protected]'
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?
CodePudding user response:
We can do a regex replacement with the help of a callback function:
var variables = [
{name: '%NAME%', value: 'joe'},
{name: '%EMAIL%', value: '[email protected]'},
{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.
CodePudding user response:
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));
CodePudding user response:
Issues.
- You have not updated
inputString
after string replace.
I have made use of below logic.
- Loop through variables first.
- Replace the values if any of the value consist of node from variable array itself (in our case replace %NAME%@mail.com as [email protected])
- Use this replaced array to perform replacement of string values from
inputString
. - Use
replaceAll
instead ofreplace
to handle multiple ovvurance of same variable.
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;
// First replace variables
for (let i = 0; i < variables.length; i ) {
const node = variables.find(item => item.value.includes(variables[i].name));
if (node) {
node.value = node.value.replaceAll(variables[i].name, variables[i].value);
}
}
for (let i = 0; i < variables.length; i ) {
output = output.replaceAll(variables[i].name, variables[i].value);
}
return output;
}
console.log(doMagic(variables, inputString))
CodePudding user response:
You can use replaceAll method to replace all the occurrence and loop twice.
function doMagic(variables, inputString) {
let output = inputString;
for (let i = 0; i < variables.length; i ) {
output = output.replaceAll(variables[i].name, variables[i].value);
}
for (let i = 0; i < variables.length; i ) {
output = output.replaceAll(variables[i].name, variables[i].value);
}
return output;
}
CodePudding user response:
My solution with use "reduce"
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(string, variables) {
const replaceVar = (s, v) =>
v.reduce((prev = "", { name, value }) => prev.replace(name, value), s);
const fixedVariables = variables.map((v) => ({
...v,
value: replaceVar(v.value, variables)
}));
return replaceVar(string, fixedVariables);
}
console.log(doMagic(inputString, variables));
Also if you want, you can modify my code to prototype, like this:
const inputString =
"Hi, my name is %NAME%, I like %HOBBY%, you can contact me at %EMAIL%";
String.prototype.doMagic = function (variables) {
const replaceVar = (s, v) =>
v.reduce((prev = "", { name, value }) => prev.replace(name, value), s);
const fixedVariables = variables.map(({ value, ...rest }) => ({
...rest,
value: replaceVar(value, variables)
}));
return replaceVar(this, fixedVariables);
};
console.log(
inputString.doMagic([
{ name: "%NAME%", value: "joe" },
{ name: "%EMAIL%", value: "%NAME%@mail.com" },
{ name: "%HOBBY%", value: "tennis" }
])
)