I'm currently trying to parse some user input into some regex groups so I can put the following inputs into the outputs.
The current regex I have is
^[0-9] [d,D,h,H,m,M]$
This successfully matches a single date, for example 1d
or 2h
. However, I need it to dynamically work for every single one, even if some are not provided by the user.
input: "5d"
output: {days: 5, hours: 0, minutes: 0}
input: "1d 2h"
output: {days: 1, hours: 2, minutes: 0}
input: "1d 5h 2m"
output: {days: 1, hours: 5, minutes: 2}
input: "2m"
output: {days: 0, hours: 0, minutes: 2}
The output doesn't necessarily have to be in a js object, simply using regex groups would also be beneficial and something I could work with.
Any help would be very appreciated as I'm not sure what else to do.
CodePudding user response:
You can use RegExp.exec()
to get all global matches with a single regex:
function parseDate(input)
{
const reg = /([0-9] )([dhm])(?=[0-9\s]|$)/gi,
result = {days: 0, hours: 0, minutes: 0},
map = {d: "days", h: "hours", m: "minutes"};
let match;
while((match = reg.exec(input.value)))
result[map[match[2]]] = match[1]; //this will sum multiple matched values ie "1d 2d 3d" will become 6 days remove " " from " =" if this behaviour is not desired
console.clear();
console.log(result);
}
parseDate(dateInput);
<input id="dateInput" oninput="parseDate(this)" value="3d 2h 1m">
CodePudding user response:
You could expand your regex to include three named capture groups for the days, hours and minutes, then use the group values to populate an output object:
const parseInput = s => {
let res = regex.exec(s) || {}
return {
days : res.groups.days || 0,
hours : res.groups.hours || 0,
minutes : res.groups.minutes || 0
}
}
const input = [ "5d", "1d 2h", "1d 5h 2m", "2m"]
const regex = /(?:(?<days>\d )[Dd])?\s*(?:(?<hours>\d )[Hh])?\s*(?:(?<minutes>\d )[Mm])?/
const result = input.map(parseInput)
console.log(result)
CodePudding user response:
Here is a way if you can live with 3 regex to fill the object:
let input = [
'5d', // {days: 5, hours: 0, minutes: 0}
'1d 2h', // {days: 1, hours: 2, minutes: 0}
'1d 5h 2m', // {days: 1, hours: 5, minutes: 2}
'2m' // {days: 0, hours: 0, minutes: 2}
].forEach(str => {
let d = str.match(/\b([0-9] )d\b/);
let h = str.match(/\b([0-9] )h\b/);
let m = str.match(/\b([0-9] )m\b/);
let obj = {
days: d ? Number(d[1]) : 0,
hours: h ? Number(h[1]) : 0,
minutes: m ? Number(m[1]) : 0,
}
console.log(str ' => ' JSON.stringify(obj));
});
Result:
5d => {"days":5,"hours":0,"minutes":0}
1d 2h => {"days":1,"hours":2,"minutes":0}
1d 5h 2m => {"days":1,"hours":5,"minutes":2}
2m => {"days":0,"hours":0,"minutes":2}
CodePudding user response:
you can use a function like this
const myfun = (s) => {
const days = s.match(/[0-9] [d,D]/) ? s.match(/[0-9] [d,D]/)[0] : "0d"
const hours = s.match(/[0-9] [h,H]/) ? s.match(/[0-9] [h,H]/)[0] : "0d"
const minutes = s.match(/[0-9] [m,M]/) ? s.match(/[0-9] [m,M]/)[0] : "0d"
return {
days: days.slice(0, -1),
hours: hours.slice(0, -1),
minutes:minutes.slice(0, -1)
}
}
console.log(myfun("5d")) // {days: 5, hours: 0, minutes: 0}
console.log(myfun("1d 2h")) // { days: '1', hours: '2', minutes: '0' }
console.log(myfun("1d 5h 2m")) // { days: '1', hours: '5', minutes: '2' }
console.log(myfun("2m")) // { days: '0', hours: '0', minutes: '2' }
console.log(myfun("randomString")) // { days: '0', hours: '0', minutes: '0' }