Here's what I would like to be able to do:
function convertVersionToNumber(line) {
const groups = line.matchAll(/^# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/g);
return parseInt(groups[1] + groups[2] + groups[3]);
}
convertVersionToNumber("# 1.03.00")
Here's what I would like to be able to do:
function convertVersionToNumber(line) {
const groups = line.matchAll(/^# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/g);
return parseInt(groups[1] + groups[2] + groups[3]);
}
convertVersionToNumber("# 1.03.00")
This doesn't work because groups
is an IterableIterator<RegExpMatchArray>
, not an array. Array.from
doesn't seem to turn it into an array of groups either. Is there an easy way (ideally something that can fit on a single line) that can convert groups
into an array?
The API of that IterableIterator<RegExpMatchArray>
is a little inconvenient, and I don't know how to skip the first element in a for...of
. I mean, I do know how to use both of these, it just seems like it's going to add 4+ lines so I'd like to know if there is a more concise way.
I am using typescript, so if it has any syntactic sugar to do this, I'd be happy to use that.
Share Improve this question edited Oct 5, 2021 at 5:14 Daniel Kaplan asked Sep 1, 2021 at 5:38 Daniel KaplanDaniel Kaplan 67.7k57 gold badges269 silver badges403 bronze badges 3-
Can you try wrapping the
line.matchAll
withArray.from
– zecuria Commented Sep 1, 2021 at 5:42 - @zecuria I tried that before I asked the question actually. I don't know what that it is returning, but it doesn't seem to be returning it into an array. – Daniel Kaplan Commented Sep 1, 2021 at 5:44
-
@zecuria thank god for typescript. My IDE tells me it is returning
RegExpMatchArray[]
. But that can't be added together. – Daniel Kaplan Commented Sep 1, 2021 at 5:46
2 Answers
Reset to default 41) matchAll
will return an Iterator object Iterator [RegExp String Iterator]
result
will contain an Iterator and when you use the spread operator It will give you all matches. Since it contains only one match so It contains a single element only.
[ '# 1.03.00', '1', '03', '00', index: 0, input: '# 1.03.00', groups: undefined ]
Finally, we used a spread operator to get all value and wrap it in an array
[...result]
function convertVersionToNumber(line) {
const result = line.matchAll(/^# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/g);
const groups = [...result][0];
return parseInt(groups[1] + groups[2] + groups[3]);
}
console.log(convertVersionToNumber("# 1.03.00"));
Since you are using regex i.e /^# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/
2) If there are multiple matches then yon can spread results in an array and then use for..of
to loop over matches
function convertVersionToNumber(line) {
const iterator = line.matchAll(/# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/g);
const results = [...iterator];
for (let arr of results) {
const [match, g1, g2, g3] = arr;
console.log(match, g1, g2, g3);
}
}
convertVersionToNumber("# 1.03.00 # 1.03.00");
Alternate solution: You can also get the same result using simple match also
function convertVersionToNumber(line) {
const result = line.match(/\d/g);
return +result.join("");
}
console.log(convertVersionToNumber("# 1.03.00"));
You do not need .matchAll
in this concrete case. You simply want to match a string in a specific format and re-format it by only keeping the three captured substrings.
You may do it with .replace
:
function convertVersionToNumber(line) {
return parseInt(line.replace(/^# (\d)\.(\d{2})\.(\d{2})[\s\S]*/, '$1$2$3'));
}
console.log( convertVersionToNumber("# 1.03.00") );
You may check if the string before replacing is equal to the new string if you need to check if there was a match at all.
Note you need to escape dots to match them as literal chars.
The ^# (\d)\.(\d{2})\.(\d{2})[\s\S]*
pattern matches
^
- start of string#
- space +#
(\d)
- Group 1: a digit\.
- a dot(\d{2})
- Group 2: two digits\.
- a dot(\d{2})
- Group 3: two digits[\s\S]*
- the rest of the string (zero or more chars, as many as possible).
The $1$2$3
replacement pattern is the concatenated Group 1, 2 and 3 values.