0

I am currently struggling with how to solve nested grouping of data.

The initial structure is given and my grouped structure below as well as my approach can be adjusted.

My idea was to have the array of objects grouped by multiple parameters in a nested way. Let me show an example structure:

- City: Zurich
-- Date: 2024/09/12
--- All entries of that city/date
-- Date yyyy/mm/dd
--- More entries
- City: Berlin
-- Date: 2024/09/12
--- All entries of that city/date

If there is other ways to solve this instead of groupBy, please help me understand how to approach it.

The data

My initial array looks like this (fetched as JSON data):

[
  {
    "_id": "123",
    "title": "Musician 1",
    "date": "2024-09-12T00:00:00.000",
    "city": "zurich",
    "country": "ch"
  },
  {
    "_id": "124",
    "title": "Musician 2",
    "date": "2024-09-14T00:00:00.000",
    "city": "berlin",
    "country": "de"
  },
  {
    "_id": "125",
    "title": "Musician 3",
    "date": "2024-09-14T00:00:00.000",
    "city": "berlin",
    "country": "de"
  },
  {
    "_id": "126",
    "title": "Musician 4",
    "date": "2024-10-24T00:00:00.000",
    "city": "zurich",
    "country": "ch"
  }
]

My approach (groups)

My idea is to add an object that has the information on what key is grouped and what value. Something like this:

[
  {
    "groupBy": "country",
    "value": "ch",
    "data": [
      {
        "_id": "123",
        "title": "Musician 1",
        "date": "2024-09-12T00:00:00.000",
        "city": "zurich",
        "country": "ch"
      },
      {
        "_id": "126",
        "title": "Musician 4",
        "date": "2024-10-24T00:00:00.000",
        "city": "zurich",
        "country": "ch"
      }
    ]
  },
  {
    "groupBy": "country",
    "value": "de",
    "data": [
      {
        "_id": "124",
        "title": "Musician 2",
        "date": "2024-09-14T00:00:00.000",
        "city": "berlin",
        "country": "de"
      },
      {
        "_id": "125",
        "title": "Musician 3",
        "date": "2024-09-14T00:00:00.000",
        "city": "berlin",
        "country": "de"
      }
    ]
  }
]

And the nested groupBy would look like this:

[
  {
    "groupBy": "country",
    "value": "ch",
    "data": [
      {
        "groupBy": "date",
        "value": "2024-09-12",
        "data": [
          {
            "_id": "123",
            "title": "Musician 1",
            "date": "2024-09-12T00:00:00.000",
            "city": "zurich",
            "country": "ch"
          }
        ]
      },
      {
        "groupBy": "date",
        "value": "2024-10-24",
        "data": [
          {
            "_id": "126",
            "title": "Musician 4",
            "date": "2024-10-24T00:00:00.000",
            "city": "zurich",
            "country": "ch"
          }
        ]
      }
    ]
  },
  {
    "groupBy": "country",
    "value": "de",
    "data": [
      {
        "groupBy": "date",
        "value": "2024-09-14",
        "data": [
          {
            "_id": "124",
            "title": "Musician 2",
            "date": "2024-09-14T00:00:00.000",
            "city": "berlin",
            "country": "de"
          },
          {
            "_id": "125",
            "title": "Musician 3",
            "date": "2024-09-14T00:00:00.000",
            "city": "berlin",
            "country": "de"
          }
        ]
      }
    ]
  }
]

This looks kinda repetitive, and I am not sure how simple that will be to code.

My idea is to build this structure with this code workflow (in JavaScript):

  1. Call groupByNested(data, ['country', 'date'])
    1. Creates a new array with the unique data of 'country'
    2. Loop through the data array and save every object that equals the parameter1 (country) to its new structure
    3. The data Array is now 2-dimensional
    4. When finished, loop through the new Array
      1. Recursively call groupByNested(GroupedArray1, ['date']) but remove the parameter that was already done (country)
      2. If parameter array is empty return the array

As soon as I have the grouped array, I can just create nested loops to actually use it.

This sounds all overly complicated to me and I would be happy if you could provide me with easier ideas/solutions for this problem.

2
  • 2
    Are you asking us if your target data structure can be improved? Or is the target data structure a fixed requirement and you are asking us if your approach to build it is ok? If it is the former: what is the purpose behind the grouping? What kind of use case are you having in mind? Please edit the question and clarify.
    – Doc Brown
    Commented Sep 19, 2023 at 21:13
  • @DocBrown only the initial data is given. Groups seemed logical to because it can just be looped over them with the correct structure given. I edited my question, so it's clear that my approach and the target data can be adjusted.
    – Dollique
    Commented Sep 19, 2023 at 22:05

1 Answer 1

-1

I've written some example code that I think does what you're asking for, grouping your example data by country code and removing the country code data from the individual entries.

Hopefully I've broken it down clearly enough that even if I didn't fully grasp your intentions I've given you enough to work with / figure out how to manipulate your data the way you want.

Hope this helps!

// your example data
const initialData = [ 
    {
         "_id": "123",
         "title": "Musician 1",
         "date": "2024-09-12T00:00:00.000",
         "city": "zurich",
         "country": "ch"
    },
    {
         "_id": "124",
         "title": "Musician 2",
         "date": "2024-09-14T00:00:00.000",
         "city": "berlin",
         "country": "de"
    },
    {
         "_id": "125",
         "title": "Musician 3",
         "date": "2024-09-14T00:00:00.000",
         "city": "berlin",
         "country": "de"
    },
    {
         "_id": "126",
         "title": "Musician 4",
         "date": "2024-10-24T00:00:00.000",
         "city": "zurich",
         "country": "ch"
    }
]
const getCountryCodesFromData = (data) => { //get all country codes from available data
    let result = [];
    initialData.forEach( (item) => {
        if ( !result.includes( item.country ) ) {
             result.push(item.country);
        }
    });
    return result;
}

const getDataForCountry = ( data, countryCode ) => { //get data for a single country code
    const result = data.filter( item => item.country === countryCode );
  //next line removes the country data from the individual entries;
    result.forEach((item)=> delete item.country);
    return result;
}

const groupDataByCountry = (data, sort=false, reverse=false) => {
    let result = {};
    let countryCodes = getCountryCodesFromData(data);
  
    // optional abc / reverse abc sorting of country codes
    if (sort) {
        countryCodes.sort();
        if (reverse) {
            countryCodes.reverse();
        }
    }
    countryCodes.forEach( ( countryCode ) => {
        result[countryCode] = getDataForCountry( data, countryCode );
  });
  return result;
}

//get data grouped by countries (reverse abc country code order)
const outputText = JSON.stringify(groupDataByCountry(initialData, true, true));

//output to console
console.log(outputText);

Not the answer you're looking for? Browse other questions tagged or ask your own question.