Grouping the array items, But the key is Array

Viewed 67

Group the Array item by one of its property, Problem is, that property is array.

Rules: Every Items in that property must be same to make it in single group.

Sample Array:

 [{name:'classOne',id:"c1",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"}]},
 {name:'classTwo',id:"c2",student:[{name:'student1',id:"student1"}]},
{name:'classThree',id:"c3",student:[{name:'student3',id:"student3"}]},
{name:'classFour',id:"c4",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"}]},
{name:'classFive',id:"c4",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"},{name:'student3',id:"student3"}]}
]

Expected Output:

{
    key1:[
        {name:'classOne',id:"c1",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"}]
        {name:'classFour',id:"c4",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"}]
    ],
    key2:[
        {name:'classTwo',id:"c2",student:[{name:'student1',id:"student1"}]},
    ],
    key3:[
        {name:'classThree',id:"c3",student:[{name:'student3',id:"student3"}]},
    ],
    key4:[
        {name:'classFive',id:"c4",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"},{name:'student3',id:"student3"}]}
    ]
}

My sample Function

export function groupByArrayKey<T>(key: string, arrayValue: T[]) {
    let result = {};
    return arrayValue.reduce((result, currentVal) => {
        const currentArray = getDeepValue(currentVal, key);
        const resultKey = currentArray[0].id;
        const keyWithLen = resultKey + currentArray.length;
        if (resultKey in result) {
            const resultArray = getDeepValue(result[resultKey][0], key);
            const isEql = isEqual(resultArray, currentArray);
            if (isEql) {
                (result[resultKey] = result[resultKey] || []).push(currentVal);
            } else {
                (result[keyWithLen] = result[keyWithLen] || []).push(currentVal);
            }
        } else if (keyWithLen in result) {
            const resultArray = getDeepValue(result[keyWithLen][0], key);
            const isEql = isEqual(resultArray, currentArray);
            if (isEql) {
                delete result[keyWithLen];
                (result[resultKey] = result[resultKey] || []).push(resultArray, currentVal);
            } else {
                const dummyKey = Math.random();
                (result[dummyKey] = result[dummyKey] || []).push(currentVal);
            }
        } else {
            console.log('third');

            (result[resultKey] = result[resultKey] || []).push(currentVal);
        }
        return result;
    }, {});
}

expect final output can be "array of array" / "object of array", anything is fine.

GroupBy: Student

The below function is working, But, is there any other to write it, in compact way?

1 Answers

One option would be to create an object whose properties are the stringified students. On every iteration over the input, stringify the students to find the key to look up. If the key doesn't exist on the object, create an array there. Then push to the array.

For example, an input object of { name: 'name', student: ['a', 'b'] } as the first item in the input array would result in the object looking like this on the first iteration:

{
  '["a","b"]': [{ name: 'name', student: ['a', 'b'] }]
}

At the end, take the object values:

const input = [
  {name:'classOne',id:"c1",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"}]},
  {name:'classTwo',id:"c2",student:[{name:'student1',id:"student1"}]},
  {name:'classThree',id:"c3",student:[{name:'student3',id:"student3"}]},
  {name:'classFour',id:"c4",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"}]},
  {name:'classFive',id:"c4",student:[{name:'student1',id:"student1"},{name:'student2',id:"student2"},{name:'student3',id:"student3"}]}
];

const groupByArrayKey = (key, inputArr) => {
  const outputArraysByStringifiedValue = {};
  for (const item of inputArr) {
    const key = JSON.stringify(item.student);
    if (!outputArraysByStringifiedValue[key]) outputArraysByStringifiedValue[key] = [];
    outputArraysByStringifiedValue[key].push(item);
  }
  return Object.values(outputArraysByStringifiedValue);
}

console.log(groupByArrayKey('student', input));

Related