I have a small piece of code that I am trying to do a replacement on. There are two data objects. One is a list of URL's that contain a {variable}, and the other is an object of the replacement values for those variables.
I have created some code to try and get it working but I think there is probably a more efficient way of handling this.
// Content we will look through and replace variables in
let urls = [
'http://www.example.com/{var1}/{var2}',
'http://www.example.com/{var1}/{var4}',
];
// Data used for the replacement
let variables = [{
variable: 'var1',
value: '123'
},
{
variable: 'var2',
value: '456'
},
{
variable: 'var4',
value: '789'
}]
// Will hold the final URLs
let finalURLs = [];
// Loop over all URLS
for (let index = 0; index < urls.length; ++index) {
// Loop over all variables
for (let d = 0; d < data.length; ++d) {
// Set the replaced URL
let u = urls[index].replace('{' + data[d].variable + '}', data[d].value);
finalURLs.push(u);
}
}
// Desired output
finalURLs = [
'http://www.example.com/123/456',
'http://www.example.com/123/789'
]
I'm sure I am way off on this but looking for some pointers on what to do.
5 Answers 5
You could take an object for the replacement strings and replace all found values.
var urls = ['http://www.example.com/{var1}/{var2}', 'http://www.example.com/{var1}/{var4}'],
vars = { var1: '123', var2: '456', var4: '789' },
result = urls.map(s => s.replace(/\{([^}]*?)\}/g, (_, v) => v in vars ? vars[v] : v));
console.log(result);
4 Comments
_ is a common sign, that this parameter is not used.{var} and v is the same thing but without parenthesis, can you explain me that?You can use Array.prototype.map(), Array.prototype.forEach() and String.prototype.replace(). Use a regular expression to apply the replacement globally.
const urls = [
'http://www.example.com/{var1}/{var2}',
'http://www.example.com/{var1}/{var4}',
];
const variables = [
{ variable: 'var1', value: '123' },
{ variable: 'var2', value: '456' },
{ variable: 'var4', value: '789' }
];
const result = urls.map(url => {
variables.forEach(({ variable, value }) => {
url = url.replace(new RegExp(`{${variable}}`, 'g'), value);
});
return url;
});
console.log(result);
1 Comment
You keep on replacing in the original value of urls[index], not the value that resulted from the previous replacement.
for (let index = 0; index < urls.length; ++index) {
let cur_url = urls[index];
// Loop over all variables
for (let d = 0; d < data.length; ++d) {
// Set the replaced URL
cur_url = cur_url.replace('{' + data[d].variable + '}', data[d].value);
}
finalURLs.push(cur_url);
}
Comments
One option would be to use a regular expression to match every variable surrounded by brackets, and then look up the replacer in an object indexed by variable, whose values are the replacements:
// Content we will look through and replace variables in
let urls = [
'http://www.example.com/{var1}/{var2}',
'http://www.example.com/{var1}/{var4}',
];
// Data used for the replacement
let variables = [{
variable: 'var1',
value: '123'
},
{
variable: 'var2',
value: '456'
},
{
variable: 'var4',
value: '789'
}];
const replacements = variables.reduce((a, { variable, value }) => {
a[variable] = value;
return a;
}, {});
const pattern = new RegExp(
Object.keys(replacements).map(needle => `{${needle}}`).join('|'),
'g' // global match; replace all
);
const newUrls = urls.map(url => (
url.replace(pattern, (needleWithBrackets) => {
// Trim out the leading and trailing brackets:
const needle = needleWithBrackets.slice(1, needleWithBrackets.length - 1);
return replacements[needle];
})
));
console.log(newUrls);
Of course, it would be nicer if you can declare the replacements upfront:
// Content we will look through and replace variables in
let urls = [
'http://www.example.com/{var1}/{var2}',
'http://www.example.com/{var1}/{var4}',
];
const replacements = {
var1: 123,
var2: 456,
var4: 789
};
const pattern = new RegExp(
Object.keys(replacements).map(needle => `{${needle}}`).join('|'),
'g' // global match; replace all
);
const newUrls = urls.map(url => (
url.replace(pattern, needleWithBrackets => replacements[needleWithBrackets.slice(1, needleWithBrackets.length - 1)])
));
console.log(newUrls);
Comments
This seems like it can be solved with a template string.
const variables = { var1: '123', var2: '323', var4:'254'}
const finalUrls = [
`http://www.example.com/${variables.var1}/{variables.var2}`,
`http://www.example.com/${variables.var1}/{variables.var4}`
]
I hope I understood your exact case.
Another note, If variables could contain special characters you should use encodeURI
datai think it should bevariablesdatainstead ofvariables. There are a few issues, but the question was one of efficiency, and there's really nothing to improve there. He needs two nested loops, regardless if he uses for-loops or map()/forEach() instead. Nothing wrong with it conceptually, he just needs to iron out the bugs.