Home > Software design >  Regex to match user input and convert into Javascript object
Regex to match user input and convert into Javascript object

Time:08-24

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' }

  • Related