替换字符串中的值(如果它们存在于变量数组中)
Replace values from a string if they are present in an array of variables
具有以下对象数组:
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%`;
该函数应将以下字符串作为参数 variables
和 inputString
以及 return:
'Hi, my name is joe, I like tennis, you can contact me at joe@mail.com'
到目前为止的功能如下:
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;
}
不幸的是,这只会找到一次,以防出现更多,并且它不会进入嵌套变量,例如 %EMAIL%
.
有什么改进的想法吗?
您可以使用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;
}
我们可以在回调函数的帮助下进行正则表达式替换:
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);
这里的策略是首先从地图构建名称的正则表达式替换。我们对输入字符串中的这些名称进行全局正则表达式搜索。对于每个匹配项,回调函数都会将名称替换为地图中的值。
您可以进行递归调用,直到字符串中没有剩余变量
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));
问题。
- 字符串替换后您还没有更新
inputString
。
我使用了以下逻辑。
- 首先遍历变量。
- 如果任何值由变量数组本身的节点组成,则替换值(在我们的例子中,将 %NAME%@mail.com 替换为 joe@mail.com)
- 使用这个替换数组来替换
inputString
. 中的字符串值
- 使用
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))
我使用“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));
另外,如果你愿意,你可以将我的代码修改为原型,如下所示:
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" }
])
)
通过数组向后循环,并使用 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));
使用正则表达式和 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));
有点冗长的版本,但如果你需要在一次迭代中完成,迭代每个字符,当你得到第二个 %(意味着结束)时,然后寻找字符串的替换。
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))
具有以下对象数组:
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%`;
该函数应将以下字符串作为参数 variables
和 inputString
以及 return:
'Hi, my name is joe, I like tennis, you can contact me at joe@mail.com'
到目前为止的功能如下:
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;
}
不幸的是,这只会找到一次,以防出现更多,并且它不会进入嵌套变量,例如 %EMAIL%
.
有什么改进的想法吗?
您可以使用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;
}
我们可以在回调函数的帮助下进行正则表达式替换:
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);
这里的策略是首先从地图构建名称的正则表达式替换。我们对输入字符串中的这些名称进行全局正则表达式搜索。对于每个匹配项,回调函数都会将名称替换为地图中的值。
您可以进行递归调用,直到字符串中没有剩余变量
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));
问题。
- 字符串替换后您还没有更新
inputString
。
我使用了以下逻辑。
- 首先遍历变量。
- 如果任何值由变量数组本身的节点组成,则替换值(在我们的例子中,将 %NAME%@mail.com 替换为 joe@mail.com)
- 使用这个替换数组来替换
inputString
. 中的字符串值
- 使用
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))
我使用“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));
另外,如果你愿意,你可以将我的代码修改为原型,如下所示:
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" }
])
)
通过数组向后循环,并使用 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));
使用正则表达式和 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));
有点冗长的版本,但如果你需要在一次迭代中完成,迭代每个字符,当你得到第二个 %(意味着结束)时,然后寻找字符串的替换。
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))