Reputation: 935
3 examples of input:
"13-4h50m2s"
"13-4h2s"
"13-50m"
Preferred code:
const [hours = 0, minutes = 0, seconds = 0] = input.match(some_regexp)
Wanted output {hours,minutes,seconds} for the 3 examples:
{hours: 4, minutes: 50, seconds: 2}
{hours: 4, minutes: 0, seconds: 2}
{hours: 0, minutes: 50, seconds: 0}
Regex I've tried: /(\d+)?[a-z](\d+)?[a-z]?(\d+)?[a-z]?/
. But then the second example doesn't work.
Edit: The input can be expected to be sorted in the right order (h,m,s). And it doesn't matter if the values are stored as strings or numbers.
Edit 2:
Sorry for the late updates, actually the 13-
part of the input can be ignored as well, but it doesn't make big of a difference and can easily be adjusted anyways.
Upvotes: 0
Views: 78
Reputation: 935
So I actually got a working solution I'm satisfied with:
const inputs = [
'1h2m3s',
'4h5m',
'6m',
'7h8s',
'9m10s'
]
const re = /(?<hours>\d+(?=h))?[hms]?(?<minutes>\d+(?=m))?[hms]?(?<seconds>\d+(?=s))?/
for (str of inputs) {
const match = re.exec(str)
const {hours = 0, minutes = 0, seconds = 0} = match.groups
console.log({hours,minutes,seconds})
}
Strings and numbers are mixed but that's OK, and it works as long as the order of h,m,s is correct.
I used optional named capturing groups with lookahead for the respective time-units, and then optional [hms]
character sets in between.
Upvotes: 1
Reputation: 350310
You could match the digits and suffix, and then use Object.fromEntries
to turn that result into an object. Use an object initialiser with spread syntax to get 0 for non-populated properties:
const parse = s =>
({h: 0, m: 0, s: 0, ...
Object.fromEntries(s.match(/\d+[msh]/g).map(m => [m[m.length-1], parseInt(m)]))
});
let inputs = [
"13-4h50m2s",
"13-2s4h",
"13-50m"
];
console.log(inputs.map(parse));
NB/ This reuses the single letters h, m, s as property names.
Upvotes: 2
Reputation: 7616
This should answer your question:
const labelMap = { h: 'hours', m: 'minutes', s: 'seconds' };
[
"13-4h50m2s",
"13-2s4h",
"13-50m"
].forEach((str) => {
let obj = { hours: 0, minutes: 0, seconds: 0 };
str.replace(/(\d+)([hms])/g, (m, p1, p2) => {
obj[labelMap[p2]] = parseInt(p1, 10);
});
console.log(JSON.stringify(obj));
});
Output:
{"hours":4,"minutes":50,"seconds":2}
{"hours":4,"minutes":0,"seconds":2}
{"hours":0,"minutes":50,"seconds":0}
Notes:
labelMap
maps from your input unit to the desired output object key/(\d+)([hms])/g
Upvotes: 2