Home > OS >  Lodash filter to group objects
Lodash filter to group objects

Time:01-25

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

CodePudding user response:

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; }

CodePudding user response:

You can use the reduce() method to group the elements in the array by ID and push the different elements in the arrays in the result. Here's an example of how you can do that:

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: []
    }
];

let result = data.reduce((acc, curr) => {
  let existing = acc.find(i => i.id === curr.id);
  if (existing) {
    existing.elements = Array.from(new Set(existing.elements.concat(curr.elements)));
    existing.files = existing.files.concat(curr.files);
  } else {
    acc.push(curr);
  }
  return acc;
}, []);

console.log(result)

  • Related