Search code examples
javascriptjsontypescriptinterfacecallback

Group data from JSON in callback function in Typescript


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' } ]
}

Solution

  • 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 { }