Ad

Reformat List To Grouped Structure

I use knockout with SharePoint, I get data using getJSON query to the list of all news. I need to create a sidebar with chronological grouped list with following structure: Year -> Month -> News title.

I already set up my view and can display all data in the format that's in initialData set.

Could you please help me to reformat this list:

var obj = [{  
            "Year":"2018",
            "Month":"January",
            "Title":"News 18 January 2018"
          },
          {...}];

to this view:

var initialData = 
[{
    Year: "2018",
    Months: [{
        Month: "January",
        News: [
            {Title: "News 18 January 2018"},
            {Title: "News 23 January 2018"}]
            },
        {Month: "February",
        News: [{...}]},
        ]
    },{ Year: "2017", Months: [{...}]
}]

I tried Object.keys with forEach loop, for loop, but totally confused.

Ad

Answer

You can't solve this by using just a single forEach loop or Object.keys. You will have to group objects on multiple keys and in multiple levels.

First, build an object with years and months as keys, to be able to find the matching arrays for each object quickly. Then expand this key-value map to a nested array.

var years = {};

obj.forEach(function(o) {
  years[o.Year] = years[o.Year] || { months: {} };
  years[o.Year].months[o.Month] = years[o.Year].months[o.Month] || [];
  years[o.Year].months[o.Month].push(o.Title);
});

var initialData = Object.keys(years).map(function(year) {
  return {
    Year: year,
    Months: Object.keys(years[year].months).map(function(month) {
      return {
        Month: month,
        News: years[year].months[month].map(function(title) {
          return {
            Title: title,
          };
        })
      };
    })
  };
});

Ad
source: stackoverflow.com
Ad