[英]Replace values from a string if they are present in an array of variables
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: function 应采用 arguments
variables
和inputString
并返回以下字符串:
'Hi, my name is joe, I like tennis, you can contact me at joe@mail.com'
Here is the function so far:到目前为止,这是 function:
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%
.不幸的是,这只会发现一次,以防万一有更多,并且它不会将 go 放入嵌套变量中,例如
%EMAIL%
。
Any ideas to improve?有什么改进的想法吗?
We can do a regex replacement with the help of a callback function:我们可以在回调 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.这里的策略是首先从 map 构建名称的正则表达式替换。我们对输入字符串中的这些名称进行全局正则表达式搜索。 For each match, the callback function replaces the name with the value from the map.
对于每个匹配项,回调 function 会将名称替换为 map 中的值。
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));
Looping backwards through the array, and using replaceAll() should do the trick.向后遍历数组,并使用 replaceAll() 应该可以解决问题。
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.使用 regex 和 while(regex.test.output()) 也可以解决问题。
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 can use replaceAll method to replace all the occurrence and loop twice.您可以使用 replaceAll 方法替换所有出现并循环两次。
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;
}
Issues.问题。
inputString
after string replace.inputString
。 I have made use of below logic.我使用了以下逻辑。
inputString
.inputString
中的字符串值。replaceAll
instead of replace
to handle multiple ovvurance of same variable.replaceAll
而不是replace
来处理同一变量的多个进化。 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))
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" } ]) )
Bit lengthy version, But if you need to do in one iteration, iterate over each character and when you get second % (means ending) then look for replacement of 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%`; const cache = variables.reduce((acc, { name, value }) => ({...acc, [name]: value, }), {}); const myReplace = (str) => { let newString = ""; let count = 0; let last = 0; let i; for (i = 0; i < str.length; i++) { if (str[i] === "%") { if (count === 0) { newString = `${newString}${str.slice(last, i)}`; count += 1; last = i; } else { newString = `${newString}${myReplace(cache[str.slice(last, i + 1)])}`; count = 0; last = i + 1; } } } newString = `${newString}${str.slice(last, i)}`; return newString; }; console.log(myReplace(inputString))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.