Search code examples
javascriptjsontypescriptdata-structuresstructure

Typescript : How to group an object of named list of objects by field name


I have to manipulate data in this wonderful language which is javascript. Until there I managed to achieve what I needed on my own but I reached my limits there.

It's quite hard to explain how my data is structured so let's make a schema. This is what I have :

    obj: {[key: string]: {name: string, type: string}[]} = 
    {
        "animals": [
          {name: "Louis", type: "dog"},
          {name: "John", type: "cat"},
          {name: "Jordan", type: "dog"},
        ]
        "cars" : [
          {name: "alpha", type: "ferrari"},
          {name: "beta", type: "ferrari"},
          {name: "charlie", type: "mercedes"},
        ]
     }

What I try to achieve is for each object, grouping the object in the list by type. This would look like this :

obj: {[key: string]: {[key: string]: {name: string, type: string}[]}} = 
{
    "animals": {
      "dog": [
          {name: "Louis", type: "dog"},
          {name: "Jordan", type: "dog"},
      ],
      "cat": [
          {name: "John", type: "cat"},
      ]
    }
    "cars" : {
      "ferrari": [
          {name: "alpha", type: "ferrari"},
          {name: "beta", type: "ferrari"},
      ],
      "mercedes": [
          {name: "charlie", type: "mercedes"},   
      ]
    }
 }

Do you have any idea how to achieve that ?


Solution

  • I think you're looking for the following (seeing as you have TypeScript in the title of your question):

    interface Value {
      name: string;
      type: string;
    }
    
    type Categorized = {
      [index: string]: Record<string, Value[]>;
    };
    
    const results = Object.entries(obj).reduce<Categorized>((mapping, [key, values]) => {
      const group: Record<string, Value[]> = {};
    
      for (const value of values) {
        if (group[value.type] === undefined) {
          group[value.type] = [value];
        } else {
          group[value.type].push(value);
        }
      }
    
      return {
        ...mapping,
        [key]: group,
      };
    }, {});