-1

I have this list in my front-end typescript file:

poMonths:

0: {id: 1, companyName: "company14", companyId: 14, flActive: true, purchaseMonth: "2019-12-15T00:00:00", purchaseMonthString: "Dec-2019" , year: 2019, month: "December"}
1: {id: 2, companyName: "company5", companyId: 5, flActive: true, purchaseMonth: "2019-12-15T00:00:00", …}
2: {id: 3, companyName: "company13", companyId: 13, flActive: true, purchaseMonth: "2019-11-15T00:00:00", …}
3: {id: 4, companyName: "company14", companyId: 14, flActive: true, purchaseMonth: "2019-11-15T00:00:00", …}
4: {id: 5, companyName: "company5", companyId: 5, flActive: true, purchaseMonth: "2019-10-15T00:00:00", …}
5: {id: 6, companyName: "company14", companyId: 14, flActive: true, purchaseMonth: "2020-09-15T00:00:00", …}
6: {id: 7, companyName: "company7", companyId: 7, flActive: true, purchaseMonth: "2020-09-15T00:00:00", …}

I would like to get a nested tree json out of it grouped by compnayName and year properties, something similar to this but in JSON format:

enter image description here

I have found this bit of code however it doesn't return the results completely, it needs to be tweaked a bit:

keys = [
    'year',
    'companyName'
  ];

groupBy() {
    const drill = (o, key, ...keys) =>
      key ? drill((o[key] = o[key] || {}), ...keys) : o;
    const result = {};
    for (const e of this.poMonths) {
      const key = drill(
        result,
        e.companyName,
        e.year,

        e.month
      );
    }
    return result;
  }

How can I get it to work?

1 Answer 1

3

You can build your tree using array.reduce(). It starts with an empty object and will assign default value whenver there's no object/array defined under specific key yet (right handside of || operator will get executed):

let input = [{id: 1, companyName: "company14", companyId: 14, flActive: true, purchaseMonth: "2019-12-15T00:00:00", year: 2019, month: "December"},
{id: 2, companyName: "company5", companyId: 5, flActive: true, purchaseMonth: "2019-12-15T00:00:00", year: 2019, month: "December"},
{id: 3, companyName: "company13", companyId: 13, flActive: true, purchaseMonth: "2019-11-15T00:00:00", year: 2019, month: "November"},
{id: 4, companyName: "company14", companyId: 14, flActive: true, purchaseMonth: "2019-11-15T00:00:00", year: 2019, month: "December"},
{id: 5, companyName: "company5", companyId: 5, flActive: true, purchaseMonth: "2019-10-15T00:00:00", year: 2019, month: "October"},
{id: 6, companyName: "company14", companyId: 14, flActive: true, purchaseMonth: "2020-09-15T00:00:00", year: 2020, month: "September"},
{id: 7, companyName: "company7", companyId: 7, flActive: true, purchaseMonth: "2020-09-15T00:00:00", year: 2020, month: "September"}]

let months = { "09": "September", "10": "October", "11": "November", "12": "December" }

let result = input.reduce((state,current) => {
   let {companyName, year, month} = current;
   
   let company = state[companyName] || (state[companyName] = {});
   let yearObj = company[year] || (company[year] = {});
   let monthArr = yearObj[month] || (yearObj[month] = []);
   monthArr.push(current);
   
   return state;
}, {});

console.log(result);

Sign up to request clarification or add additional context in comments.

5 Comments

@EfronA. modified my answer
do you know how I can have the "id" attribute at the "month" level? At the moment, id would be shown as a child underneath the month, however, each month would only have one id underneath it, so I would like to have the id at the month level. How would you do this?
@EfronA. please open another question in order to keep this one clear
Thanks, slightly different question based on your answer here: stackoverflow.com/questions/59744446/…
Great answer - quick question. What would be the easiest way to remove the brackets from the months payload => "December": [{ to "December": {. Also, is it possible to remove the duplicate keys in the nested portion (companyName, year, month)?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.