Home > Blockchain >  Replace values from a string if they are present in an array of variables
Replace values from a string if they are present in an array of variables

Time:02-10

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 of replace 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" }
  ])
)

  • Related