user2004
user2004

Reputation: 1973

Group a list of objects in nested arrays javascript

I have an array of objects as below

[
  {
      id: 10,
      regionName: "Europa",
      countryName: "Greece",
      applicationName: "Ramco",
      issueSummary: "No Reported Issues",
      resolutionEta: "",
      status: "UP"
  },
  {
      id: 9,
      regionName: "Asia PAC",
      countryName: "Singapore",
      applicationName: "Reckon",
      issueSummary: "No Reported Issues",
      resolutionEta: "",
      status: "UP"
  },
  {
      id: 7,
      regionName: "Asia PAC",
      countryName: "Thailand",
      applicationName: "Javelin",
      issueSummary: "No Reported Issues",
      resolutionEta: "",
      status: "UP"
  },
  {
      id: 8,
      regionName: "Europa",
      countryName: "Greece",
      applicationName: "Tamco",
      issueSummary: "No Reported Issues",
      resolutionEta: "",
      status: "UP"
  }
]

and I'm trying to group these objects in an array of regions, and each region should have an array of countries and each country should have an array of applications.

{
  regions: [{
    regionName: "Europe",
    countries: [
      {
        countryName: "Greece",
        applications: [
          {
            applicationName: "Ramco",
            issueSummary: "No Reported Issues",
            eta: "",
            status: "UP",
          },
          {
            applicationName: "Tamco",
            issueSummary: "No Reported Issues",
            eta: "",
            status: "UP",
          }
        ]
      },
      {
        countryName: "France",
         applications: [
          {
            applicationName: "Ramco",
            issueSummary: "No Reported Issues",
            eta: "",
            status: "UP",
          },
          {
            applicationName: "Tamco",
            issueSummary: "No Reported Issues",
            eta: "",
            status: "UP",
          }
        ]
      },
    ]
.... and so on
  },

here is what I have so far, it's working only for the regions array. I have a groupBy method and I am using it for regions and countries but this gives me separated arrays, not nested

 ngOnInit(): void {
    this.allRegions$ = this.dataService.getData();

    this.groupData();
  }

  groupData() {
    this.dataService.getData().subscribe(res => {
      this.data = res;
      const regions = this.groupBy('regions', this.data)
      const countries = this.groupBy('countries', regions)
    })
  }

  groupBy(key, array) {
    return array.reduce((all, current) => {
      const existingKey = all.find(existing => existing.key === current[key]);
      console.log(existingKey)
      if (!existingKey) {
        all.push({key: current[key], values: [current]});
      } else {
        existingKey.values.push(current);
      }
      return all;
    }, []);
  }

Upvotes: 3

Views: 778

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386570

You could take an abstract approach by using an object as reference to the nested grouping properties and build the structure as wanted.

This approach works for any depth of grouping just by adding wanted keys to the keys array.

const
    data = [{ id: 10, regionName: "Europa", countryName: "Greece", applicationName: "Ramco", issueSummary: "No Reported Issues", resolutionEta: "", status: "UP" }, { id: 9, regionName: "Asia PAC", countryName: "Singapore", applicationName: "Reckon", issueSummary: "No Reported Issues", resolutionEta: "", status: "UP" }, { id: 7, regionName: "Asia PAC", countryName: "Thailand", applicationName: "Javelin", issueSummary: "No Reported Issues", resolutionEta: "", status: "UP" }, { id: 8, regionName: "Europa", countryName: "Greece", applicationName: "Tamco", issueSummary: "No Reported Issues", resolutionEta: "", status: "UP" }],
    keys = ['regionName', 'countryName'],
    result = data
        .reduce((r, o) => {
            let key;
            keys
                .reduce((t, k) => {
                    ({ [k]: key, ...o } = o);
                    if (!t[key]) {
                        t[key] = { _: [] };
                        t._.push({ [k]: key, children: t[key]._ });
                    }
                    return t[key];
                }, r)
                ._
                .push(o);
            return r;
        }, { _: [] })
        ._;


console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions