Reputation: 8171
I am trying to refactor some code:
const newValue = value
.replace(/\{1\}/g, '<i class="ms ms-1 inline"></i>')
.replace(/\{2\}/g, '<i class="ms ms-2 inline"></i>')
... etc etc
return newValue;
I would prefer not to use replace
each time.
I have been trying the following without success:
const mapObj = {
'/\{1\}/': '<i class="ms ms-1 inline"></i>',
'/\{2\}/': '<i class="ms ms-2 inline"></i>',
...
}
const reg = new RegExp(Object.keys(mapObj).join("|"), "g");
return value.replace(reg, (m) => mapObj[m]);
For simple replaces this usually works pretty well, however because of the need to escape the special characters ({
and }
) something is clearly going wrong with my regex pattern in the mapObj
object.
Here is demo of the current simplified code.
How do I go about fixing the pattern (/\{1\}/
) in the mapObj
to get the refactored code to work?
Upvotes: 0
Views: 55
Reputation: 1
It appears that your refactor is confusing string, regular expressions, and the escape sequences for both.
Given your code...
const mapObj = {
'/\{1\}/': '<i class="ms ms-1 inline"></i>',
'/\{2\}/': '<i class="ms ms-2 inline"></i>',
...
}
const reg = new RegExp(Object.keys(mapObj).join("|"), "g");
return value.replace(reg, (m) => mapObj[m]);
The reg
regular expression will be /\/{1}\/|\/{2}\//g
, (which is looking for curly brackets surrounded by slashes,) which is not what you want. You want something like /\{1\}|\{2\}/g
The (m) => mapObj[m]
won't work as intended, because the value
string will have words like "pay {1} to cast"
, whereas mapObj[m]
is looking for keys like "\/{1}\/"
(note the slashes around the curly brackets)
What you want to do is remove the unnecessary /
slashes when converting between Regex and strings and back.
Recommended solution:
function magicReplace(value) {
mapObj = {
'{1}': '<i class="ms ms-1 inline"></i>',
'{2}': '<i class="ms ms-2 inline"></i>',
};
reg = new RegExp( Object.keys(mapObj).join("|").replace(/\{/g, '\\{').replace(/\}/g, '\\}'), "g");
return value.replace(reg, (m) => mapObj[m]);
}
magicReplace('Whenever you cast a spell, you may pay {1}.');
//Returns: 'Whenever you cast a spell, you may pay <i class="ms ms-1 inline"></i>.'
Upvotes: 0
Reputation: 1074475
If your replacments really are the same other than ms-1
for {1}
and ms-2
for {2}
, then use a capture group:
return value.replace(/\{(\d)}/g, '<i class="ms ms-$1 inline"></i>');
The $1
is the content of the capture group. That expression matches a single digit within {}
; adjust as needed.
Live Example:
function process(value) {
return value.replace(/\{(\d)}/g, '<i class="ms ms-$1 inline"></i>');
}
console.log(process("Testing {1} testing {2}"));
If the replacements vary and you really need to map them, use the function callback:
const mapObj = {
"{1}": "replacement for 1",
"{2}": "different replacement for 2"
};
return value.replace(/\{\d}/g, m => mapObj[m] || "some default");
You could use a capture group to avoid having to repeat {}
in the keys in mapObj
.
Live Example:
const mapObj = {
"{1}": "replacement for 1",
"{2}": "different replacement for 2"
};
function process(value) {
return value.replace(/\{\d}/g, m => mapObj[m] || "some default");
}
console.log(process("Testing {1} testing {2}"));
Upvotes: 1