Andrews
Andrews

Reputation: 11

Lodash filter to group objects

I have an array that I like to group by the ID, but pushing all the different elements in the arrays in the result.

let data = [
    {   id: "1", elements: ["a","b"], files: []    },
    {   id: "1", elements: ["a","b"], files: []    },
    {   id: "2", elements: ["a","b","c"],
        files: [
            { name: "test1",
              extension: "pdf"
            },
            { name: "test2",
              extension: "pdf"
            }
        ]
    },
    {   id: "2", elements: ["a","b","c"],
        files: [
            { name: "test3",
              extension: "png"
            },
            { name: "test4",
              extension: "png"
            },
            { name: "test5",
              extension: "pdf"
            }
        ]
    },
    {   id: "2", elements: ["a","b","c"], files: []
    }
];

I want a result like

result = 
[
    {
        "id": "1", "elements": [ "a", "b" ], "files": []    },
    {
        "id": "2", "elements": [ "a", "b", "c" ],
        "files": [
            { "name": "test1", "extension": "pdf" },
            { "name": "test2", "extension": "pdf" },
            { "name": "test3", "extension": "png" },
            { "name": "test4", "extension": "png" },
            { "name": "test5", "extension": "pdf" },
        ]
    }
]

How it is possible with lodash or any other process getting the desire output

Upvotes: 1

Views: 67

Answers (1)

Terry Lennox
Terry Lennox

Reputation: 30685

You can use Array.reduce() to group the items by id.

This creates an object with a property for each id, we can then use Object.values() to get the result as an array.

For the elements array, we'll also use a Set to ensure we don't duplicate elements. We only want ['a','b'] rather than ['a','b','a','b'] for example.

let data = [ {   id: "1", elements: ["a","b"], files: []    }, {   id: "1", elements: ["a","b"], files: []    }, {   id: "2", elements: ["a","b","c"], files: [ { name: "test1", extension: "pdf" }, { name: "test2", extension: "pdf" } ] }, {   id: "2", elements: ["a","b","c"], files: [ { name: "test3", extension: "png" }, { name: "test4", extension: "png" }, { name: "test5", extension: "pdf" } ] }, {   id: "2", elements: ["a","b","c"], files: [] } ];

const result = Object.values(data.reduce((acc, { id, elements, files }) => { 
    acc[id] = acc[id] || { id, elements: [], files: []};
    // Use a Set to avoid duplicates...
    acc[id].elements = [...new Set([...elements, ...acc[id].elements])];
    acc[id].files.push(...files);
    return acc;
}, {}));

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

Upvotes: 1

Related Questions