Home > Blockchain >  How can I group an array of objects by field values multiple times?
How can I group an array of objects by field values multiple times?

Time:03-01

I have an array of objects obtained from an API response and am looking to format it so that it can be used for a menu with nested items.

[
    {
        "id": 1,
        "name": "The Cool Association",
        "description": "the office",
        "country": "United Kingdom",
        "county": "North Lanarkshire",
        "town": "Airdrie",
        "address": "test addr 1",
        "postcode": null,
        "latlong": {
            "x": -3.97369,
            "y": 55.8665
        },
        "mainCategory": Hills,
        "subCategory": 17,
        "refCode": "airdrie"
    },
    {
        "id": 2,
        "name": "Test Locations",
        "description": "testing",
        "country": "United Kingdom",
        "county": "Aberdeenshire",
        "town": "Airdrie",
        "address": "test addr 1",
        "postcode": null,
        "latlong": {
            "x": -4.02652,
            "y": 55.8611
        },
        "mainCategory": Mountains,
        "subCategory": null,
        "refCode": "coat"
    },
    {
        "id": 3,
        "name": "Test Locations",
        "description": "testing",
        "country": "Scotland",
        "county": "North Lanarkshire",
        "town": "Airdrie",
        "address": "test addr 1",
        "postcode": null,
        "latlong": {
            "x": -4.02652,
            "y": 55.8611
        },
        "mainCategory": Main Category,
        "subCategory": null,
        "refCode": "test"
    },
    {
        "id": 4,
        "name": "NL Leisure",
        "description": "leisure",
        "country": "United Kingdom",
        "county": "North Lanarkshire",
        "town": "Airdrie",
        "address": "test addr 1",
        "postcode": null,
        "latlong": {
            "x": -4.02652,
            "y": 55.8611
        },
        "mainCategory": Sports,
        "subCategory": null,
        "refCode": "hello"
    }
]

I am looking to group the response by Country first, then inside country by County, then inside County by Main Category. Is this possible?

[
   "Scotland":{
      "North Lanarkshire":{
         "MainCategory":{
            "...details"
         }
      }
   },
   "UnitedKingdom":{
      "North Lanarkshire":{
         "Hills":{
            "...details"
         },
         "Sports":{
            "...details"
         }
      },
      "Aberdeenshire":{
         "Mountains":{
            "...details"
         }
      }
   }
]

I have attempted all manners of reduce and using the _.groupBy function provided by lodash but haven't been able to end up with the format I am looking for. Would it be better off formatting it at an API level? Any help appreciated

CodePudding user response:

const arr = [{
    "id": 1,
    "name": "The Cool Association",
    "description": "the office",
    "country": "United Kingdom",
    "county": "North Lanarkshire",
    "town": "Airdrie",
    "address": "test addr 1",
    "postcode": null,
    "latlong": {
      "x": -3.97369,
      "y": 55.8665
    },
    "mainCategory": 'Hills',
    "subCategory": 17,
    "refCode": "airdrie"
  },
  {
    "id": 2,
    "name": "Test Locations",
    "description": "testing",
    "country": "United Kingdom",
    "county": "Aberdeenshire",
    "town": "Airdrie",
    "address": "test addr 1",
    "postcode": null,
    "latlong": {
      "x": -4.02652,
      "y": 55.8611
    },
    "mainCategory": 'Mountains',
    "subCategory": null,
    "refCode": "coat"
  },
  {
    "id": 3,
    "name": "Test Locations",
    "description": "testing",
    "country": "Scotland",
    "county": "North Lanarkshire",
    "town": "Airdrie",
    "address": "test addr 1",
    "postcode": null,
    "latlong": {
      "x": -4.02652,
      "y": 55.8611
    },
    "mainCategory": 'Main Category',
    "subCategory": null,
    "refCode": "test"
  },
  {
    "id": 4,
    "name": "NL Leisure",
    "description": "leisure",
    "country": "United Kingdom",
    "county": "North Lanarkshire",
    "town": "Airdrie",
    "address": "test addr 1",
    "postcode": null,
    "latlong": {
      "x": -4.02652,
      "y": 55.8611
    },
    "mainCategory": 'Sports',
    "subCategory": null,
    "refCode": "hello"
  }
]
const result = arr.reduce((acc, curr) => {
  const country = acc[curr.country] || {};
  const county = country[curr.county] || {};
  const mainCategory = county[curr.mainCategory] || {};
  mainCategory[curr.name] = curr;
  county[curr.mainCategory] = mainCategory;
  country[curr.county] = county;
  acc[curr.country] = country;
  return acc;
}, {});
console.log(JSON.stringify(result, null, 2));

CodePudding user response:

Using Array#reduce:

const arr = [
  { "id": 1, "name": "The Cool Association", "description": "the office", "country": "United Kingdom", "county": "North Lanarkshire", "town": "Airdrie", "address": "test addr 1", "postcode": null, "latlong": { "x": -3.97369, "y": 55.8665 }, "mainCategory": "Hills", "subCategory": 17, "refCode": "airdrie" },
  { "id": 2, "name": "Test Locations", "description": "testing", "country": "United Kingdom", "county": "Aberdeenshire", "town": "Airdrie", "address": "test addr 1", "postcode": null, "latlong": { "x": -4.02652, "y": 55.8611 }, "mainCategory": "Mountains", "subCategory": null, "refCode": "coat" },
  { "id": 3, "name": "Test Locations", "description": "testing", "country": "Scotland", "county": "North Lanarkshire", "town": "Airdrie", "address": "test addr 1", "postcode": null, "latlong": { "x": -4.02652, "y": 55.8611 }, "mainCategory": "Main Category", "subCategory": null, "refCode": "test" },
  { "id": 4, "name": "NL Leisure", "description": "leisure", "country": "United Kingdom", "county": "North Lanarkshire", "town": "Airdrie", "address": "test addr 1", "postcode": null, "latlong": { "x": -4.02652, "y": 55.8611 }, "mainCategory": "Sports", "subCategory": null, "refCode": "hello" }
];

const res = arr.reduce((acc, { country, county, mainCategory, ...e }) => ({
  ...acc,
  [country]: {
     ...(acc[country] ?? {}),
     [county]: {
       ...(acc[country]?.[county] ?? {}),
       [mainCategory]: e
     }
  }
}), {});

console.log(res);

  • Related