downFast
downFast

Reputation: 31

How to split a string into corresponding objects?

Given this:

const MATCH_NAME = /\s+([a-z]+)\s+/i;

function parseDates(input) {
  const parts = input.split(MATCH_NAME);
  const result = {
    dates: [],
    year: null
  };

  while (parts.length > 2) {
    const [days, month, suffix] = parts.splice(0, 2);
    result.dates.push({
      month,
      days: days.split(/\D+/),
      suffix
    });
  }

  result.year = parts[0];
  return result;
}

console.log(parseDates('12-5 November 17 May 1954 CE'));
console.log(parseDates('1 January 1976 CE'));
console.log(parseDates('12 22 March 1965'));

The year obj ends up like 1976 CE while CE should be in the suffix.

Trying to get to:

Month: November
  Days: 12, 5
Month: May
  Days: 17
Year: 1954
Suffix: CE

jsFiddle here

Upvotes: 0

Views: 81

Answers (1)

Rajesh
Rajesh

Reputation: 24915

In my understanding, your pattern is something like this:

  • You have a list of values separated by spaces.
  • Values can be numeric or alphabets.
  • If Numeric,
    • If <= 31, its a day and should be pushed to days array.
    • Days can be separated by hyphens or space, if more than 1.
    • Else it is year.
  • If alphabets,
    • If it is followed by year and length is less than 3(assuming that suffix will be 2 digit and you can have a Date without date value(e.g.: "November 2007"))
    • Else it is month.

Note: If my understanding is correct, then following solution will help you. If not, please share inconsistencies.

function parseDates(input) {
  var parts = processHTMLString(input).split(/[-–,\/\s]/g);
  var result = [];
  var numRegex = /\d+/;
  var final = parts.reduce(function(temp, c) {
    if (numRegex.test(c)) {
      let num = parseInt(c);
      if (temp.year || (temp.month && num < 31)) {
        result.push(temp);
        temp = {};
      }
      temp.days = temp.days || []
      if (c.indexOf("-") >= 0) {
        temp.days = temp.days.concat(c.split("-"));
      } else if (num > 31)
        temp.year = c;
      else
        temp.days.push(c)
    } else if (c.length < 3 && temp.year) {
      temp.suffix = c
    } else {
      temp.month = c;
    }
    return temp;
  }, {});
  result.push(final);
  return result;
}

function processHTMLString(str) {
  var div = document.createElement("div");
  div.innerHTML = str;
  // This will process `&nbsp;` and any other such value.
  return div.textContent;
}

console.log(parseDates('12-5 November 2007 ce 17 May 1954 Ce'));
console.log(parseDates('1 January 1976 CE'));
console.log(parseDates('12 22 March 1965'));

Upvotes: 1

Related Questions