SPOILER ALERT ! This post will contain spoilers for solving the challenge “Convert HTML Entities”, so only read on if you have completed this challenge.
So today I was working on refactoring some challenges which I had already solved. When I re-looked at my “Convert HTML Entities” solution (below), I was like, what if there were a hundred different replacements? I did not like the thought of putting in all of the .replace statements in my code.
// original solution
function convertHTML(str) {
return str.replace(/&/g,"&")
.replace(/</g,"<")
.replace(/>/g,">")
.replace(/"/g,""")
.replace(/'/g,"'");
}
It got me to thinking about creating a new String prototype called replaceAll which would accept one parameter (conversionsObj) which would contain a mapping of all the characters needing replacements along with their corresponding replacement value.
I came up with two solutions. The first uses a regular expression and reduce to produce the “replaced” string and the second splits up the string into an array, so I could use map to iterate over the string and make each conversion before rejoining the array back into a string. One would simply need to declare an object with the necessary conversions and a string to call the function on (example below):
const conversions = {'&':'&', '<':'<','>':'>','"':'"',"'":'''};
const str = 'Dolce & Gabbana';
str.replaceAll(conversions); // results in 'Dolce & Gabbana'
I think the second is more readable, but I will need to do some testing to validate which version performs the best.
Prototype #1 (using regex expression):
// regex solution
String.prototype.replaceAll = function(conversionsObj) {
return Object.keys(conversions).reduce((newStr,find) => newStr.replace(new RegExp(find, 'g'),conversions[find]),this);
};
Prototype #2 (using map):
// Array.prototype.map solutions
String.prototype.replaceAll = function(conversionsObj) {
return this.split('').map(char => conversionsObj[char] ? char = conversionsObj[char] : char).join('');
};