I am trying to remove all the consecutive numbers using exactly RegEx with JS. I tried two ways the second one passed but I am wondering what is wrong with the first one
First try:
let a = "1 2 3 3 4 5 5 6 7 8 8 9";
a = a.split(" ").join("");
for (let i of a) {
a = a.replace(/ii/g, i);
}
console.log(a)
Second one
let a = "1 2 3 3 4 5 5 6 7 8 8 9";
a = a.split(" ").join("");
for (let i of a) {
a = a.replace(new RegExp(`(${i})(${i})`, "g"), "$1");
}
console.log(a)
CodePudding user response:
To answer your question, your first snippet is using a regular expression literal which cannot accept variables from the script. So...
/ii/g
...would match any occurrence of 'ii'
in a targeted string.
The only way to achieve this functionality is with the RegExp()
constructor which you demonstrate in the second snippet.
If the motivation behind your question is cleaner code then the following is an alternative approach:
Lookbehind assertions and capture groups in regex make situations like this really simple to achieve. No need to mess around with arrays and loops:
const removeSequentialNumbers = (string) =>
string.replaceAll(/(?<=(?<number>\d))(\s\k<number>)/g, '');
Here is the Regex101 link for your testing.
Hope this helps.
CodePudding user response:
I think the semantically correct way to do this is with named groups. It lets you match a pattern then refer back to the pattern later in your match so it allows you to identify duplicates easily.
a.replaceAll(/(?<number>\d)\s\k<number>/g, "$1")
Explanation: It matches a digit \d and it groups it with () and it gives it a name (in this case "number") then I can refer to this match with \k so I can see where the same match appears again.
Then replace with $1 replaces the whole content (in this case two matches separated with a space) with the group.
You can read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Backreferences
let a = "1 2 3 3 4 5 5 6 7 8 8 9";
const result = a.replaceAll(/(?<number>\d)\s\k<number>/g, "$1")
console.log(result)
CodePudding user response:
This can be done easier with match groups and back-references. Just make one match group that matches any number, then repeat that group at least once. To make this work, you'll also need to add a trailing space so the last number can be matched, but then later remove that space. Like this:
let a = "1 2 3 3 4 5 5 6 7 8 8 9";
let b = (a ' ').replace(/([1-9]\s)\1 /g, '$1').slice(0, -1);
console.log(b)
This method will also preserve the spaces. If you need to remove the spaces, then you can simply strip them from the result like this:
let a = "1 2 3 3 4 5 5 6 7 8 8 9";
let b = (a ' ').replace(/([1-9]\s)\1 /g, '$1').replaceAll(' ', '');
console.log(b)
I timed this approach against damonholden's answer and found that it is generally faster (run multiple times, stack snippets is a little finicky):
let a = "1 2 3 3 4 5 5 6 7 8 8 9";
console.time()
console.log(a.replaceAll(/(?<=(?<number>\d))(\s\k<number>)/g, ''));
console.timeEnd()
console.time()
console.log((a ' ').replace(/([1-9]\s)\1 /g, '$1').slice(0, -1));
console.timeEnd();
CodePudding user response:
let a = "1 2 3 3 4 5 5 6 7 8 8 9";
a = a.split(" ").join("");
let b = a.replace(/(.)\1 /g, '$1');
let c = b.split("").join(" ")
console.log(c)