Search code examples
javascriptjsonsortingobjectmultidimensional-array

Grouping objects by key and returning new object


I have array of objects that I need to sort it in JavaScript the way that suits me.

this is example of array that I have:

[
  {
    "id": "AD012014001R",
    "country": "AD",
    "series": 1,
    "issue_year": 2014
  },
  {
    "id": "AD012014002R",
    "country": "AD",
    "series": 1,
    "issue_year": 2014
  },
  {
    "id": "AT012002002R",
    "country": "AT",
    "series": 1,
    "issue_year": 2002
  },
  {
    "id": "BE011999100R",
    "country": "BE",
    "series": 1,
    "issue_year": 1999
  },
  {
    "id": "BE011999200R",
    "country": "BE",
    "series": 1,
    "issue_year": 1999
  },
  {
    "id": "BE022008001R",
    "country": "BE",
    "series": 2,
    "issue_year": 2008
  }
]

and my output should look like this:

[
  {
    "country": "AD",
    "series": [
      {
        "series": 1,
        "coins": [
          {
            "id": "AD012014001R",
            "country": "AD",
            "series": 1,
            "issue_year": 2014
          },
          {
            "id": "AD012014002R",
            "country": "AD",
            "series": 1,
            "issue_year": 2014
          }
        ]
      }
    ]
  },
  {
    "country": "AT",
    "series": [
      {
        "series": 1,
        "coins": [
          {
            "id": "AT012002002R",
            "country": "AT",
            "series": 1,
            "issue_year": 2002
          }
        ]
      }
    ]
  },
  {
    "country": "BE",
    "series": [
      {
        "series": 1,
        "coins": [
          {
            "id": "BE011999100R",
            "country": "BE",
            "series": 1,
            "issue_year": 1999
          },
          {
            "id": "BE011999200R",
            "country": "BE",
            "series": 1,
            "issue_year": 1999
          }
        ]
      },
      {
        "series": 2,
        "coins": [
          {
            "id": "BE022008001R",
            "country": "BE",
            "series": 2,
            "issue_year": 2008
          }
        ]
      }
    ]
  }
]

So my API response is must bigger but this is small part of it. I am getting array of hundred of objects that look like this and need to sort them and return them sorted first by countries and then by series under each country. I know there is lot of similar questions but I can't figure it out because my problem seams little more complicated than all of them.


Solution

  • You could take a multi ruping approach by having an array of group key and children property. Then find the group at level and build a new object or just return the children. At the end push the object.

    const
        data = [{ id: "AD012014001R", country: "AD", series: 1, issue_year: 2014 }, { id: "AD012014002R", country: "AD", series: 1, issue_year: 2014 }, { id: "AT012002002R", country: "AT", series: 1, issue_year: 2002 }, { id: "BE011999100R", country: "BE", series: 1, issue_year: 1999 }, { id: "BE011999200R", country: "BE", series: 1, issue_year: 1999 }, { id: "BE022008001R", country: "BE", series: 2, issue_year: 2008 }],
        groups = [
            ['country', 'series'],
            ['series', 'coins']
        ],
        result = data.reduce((r, o) => {
            groups
                .reduce((level, [key, children]) => {
                    let group = level.find(q => q[key] === o[key]);
                    if (!group) level.push(group = { [key]: o[key], [children]: [] });
                    return group[children];
                }, r)
                .push(o);
            return r;
        }, []);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }