skip to Main Content

I need to write a function groupBy that groups the people in the JSON data using a function given.
Below is the interface and JSON data:

interface Person {
    name: string;
    yearOfBirth: number;
    placeOfBirth: string;
}

const input: Person[] = [
    {
        name: "Andy",
        yearOfBirth: 1984,
        placeOfBirth: "New York",
    },
    {
        name: "John",
        yearOfBirth: 1995,
        placeOfBirth: "New York",
    },
    {
        name: "Bill",
        yearOfBirth: 1995,
        placeOfBirth: "Orlando",
    },
    {
        name: "Tim",
        yearOfBirth: 1989,
        placeOfBirth: "Witchita",
    },
];

Below is the code I have so far, it is no where close to working as it should but I am new to callback functions so I have been just trying to get the feel of how it works.

const groupBy = (input: Person[], func: (p: Person) => string): string[] => {

    let collect: string[] = [];
    for (let i = 0; i < input.length; i++) {
        collect[i] = func(input[i]);

    }
    return collect;
}

try {
    console.log(groupBy(input, (p: Person) => p.placeOfBirth));

}
catch (e: any) {
    console.log(e.message);

}

//This is the output from my current code:
[ 'New York', 'New York', 'Orlando', 'Witchita' ]

Below is how it should actually output when called using the console.log below:

//Example 1
//call the function which groups the data together from 'placeOfBirth':

console.log(groupBy(input, (p: Person) => p.placeOfBirth));

//Output from console.log:

{
  New York: [
    { name: 'Andy', yearOfBirth: 1984, placeOfBirth: 'New York' },
    { name: 'John', yearOfBirth: 1995, placeOfBirth: 'New York' }
  ],
  Orlando: [ { name: 'Bill', yearOfBirth: 1995, placeOfBirth: 'Orlando' } ],
  Witchita: [ { name: 'Tim', yearOfBirth: 1989, placeOfBirth: 'Witchita' } ]
}

//Example 2
//call the function which groups the data together from 'yearOfBirth':

console.log(groupBy(input, (p: Person) => p.yearOfBirth));

//Output from console.log:

{
  '1984': [ { name: 'Andy', yearOfBirth: 1984, placeOfBirth: 'New York' } ],
  '1995': [
    { name: 'John', yearOfBirth: 1995, placeOfBirth: 'New York' },
    { name: 'Bill', yearOfBirth: 1995, placeOfBirth: 'Orlando' }
  ],
  '1989': [ { name: 'Tim', yearOfBirth: 1989, placeOfBirth: 'Witchita' } ]
}

3

Answers


  1. Chosen as BEST ANSWER

    I found a solution which finally worked to group the data together. I will share the code below for anyone else looking for a similar solution:

    interface Person {
        name: string;
        yearOfBirth: number;
        placeOfBirth: string;
    }
    
    const input: Person[] = [
        {
            name: "Andy",
            yearOfBirth: 1984,
            placeOfBirth: "New York",
        },
        {
            name: "John",
            yearOfBirth: 1995,
            placeOfBirth: "New York",
        },
        {
            name: "Bill",
            yearOfBirth: 1995,
            placeOfBirth: "Orlando",
        },
        {
            name: "Tim",
            yearOfBirth: 1989,
            placeOfBirth: "Witchita",
        },
    ];
    
    function groupBy(input: Person[], groupFunc: (item: Person) => any): { [key: string]: Person[] } {
        const groups: { [key: string]: Person[] } = {};
    
        input.forEach(item => {
            const groupKey = groupFunc(item);
            if (!groups[groupKey]) {
                groups[groupKey] = [];
            }
            groups[groupKey].push(item);
        });
    
        return groups;
    }
    
    try {
        console.log(groupBy(input, (p: Person) => p.yearOfBirth));
    
    }
    catch (e: any) {
        console.log(e.message);
    }
    
    export { }
    
    

  2. Use the below function. Pass your array of objects and key name for grouping, then get grouped data by the key that you sent:

        const groupByKey = <T>(objectArray: T[], property: string) => {
          return objectArray.reduce(
              (acc: { [x: string]: any[]; }, obj: { [x: string]: any; }) => {
              const key = obj[property];
              if (!acc[key]) {
                  acc[key] = [];
              }
              acc[key].push(obj);
              return acc;
          }, 
          {});
      }
    
    //Usage:
      const groupedData = groupByKey(personsList, 'placeOfBirth');
    Login or Signup to reply.
  3. Do you have a focus on performance?

    If no, you could try this:

    function groupBy<I extends unknown>(
      input: I[],
      predicate: (i: I) => string | number
    ) {
      return input.reduce((curr, i) => {
        const key = predicate(i);
    
        return {
          ...curr,
          [key]: [...(curr[key] ?? []), i]
        };
      }, {});
    }
    

    Here a sandbox to try it out: https://codesandbox.io/s/unruffled-morse-nwjjsy?file=/src/index.ts

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search