I am receiving an Array of Objects like so
[
{
"payload":{
"correlation":{
"metadata":{
"customerId":"12345",
"project":"Project One"
}
}
}
},
{
"payload":{
"correlation":{
"metadata":{
"customerId":"12345",
"project":"Project Two"
}
}
}
},
{
"payload":{
"correlation":{
"metadata":{
"customerId":"12345",
"project":"Project Two"
}
}
}
},
{
"payload":{
"correlation":{
"metadata":{
"customerId":"54323",
"project":"Project One"
}
}
}
}
]
What I am trying to do is count all the unique customerId's per project. So for the above data, I would expect
Project One: 2
Project Two: 1 //because 12345 is shown twice for Project Two, we only want unique so count it as 1
So I can do the counts using a map, something like this
const lutProjects = new Map();
Object.entries(data).forEach(([key, value]) => {
const project = value?.payload?.correlation?.metadata?.project;
const custId = value?.payload?.correlation?.metadata?.customerId;
lutProjects.set(project, (lutProjects.get(project) || 0) 1);
});
However, this does not handle unique ids for each project, so outputs 2 and 2.
How can I also handle unique id's per project?
I have created a JSFiddle
Thanks
CodePudding user response:
If you use reduce()
to create an object with the project
as key, and the value as an array containing the customerId
, we can use includes()
to check if this customerId
is already known, and only add it to the array if not.
Then, we can use a second reduce()
to change the array ow customerId
's to the length
of the array:
const data = [{"payload":{"correlation":{"metadata":{"customerId":"12345", "project":"Project One"} } } }, {"payload":{"correlation":{"metadata":{"customerId":"12345", "project":"Project Two"} } } }, {"payload":{"correlation":{"metadata":{"customerId":"12345", "project":"Project Two"} } } }, {"payload":{"correlation":{"metadata":{"customerId":"54323", "project":"Project One"} } } } ];
let res = data.reduce((prev, cur) => {
const { customerId, project } = cur.payload.correlation.metadata;
if (!prev[project]) prev[project] = [];
if (!prev[project].includes(customerId)) {
prev[project].push(customerId);
}
return prev;
}, {});
res = Object.keys(res).reduce((prev, cur) => ({ ...prev, [cur]: res[cur].length }), {});
console.log(res);
{
"Project One": 2,
"Project Two": 1
}
CodePudding user response:
You can try quick fix with below snippet
let data = [{"payload":{"correlation":{"metadata":{"customerId":"12345","project":"Project One"}}}},{"payload":{"correlation":{"metadata":{"customerId":"12345","project":"Project Two"}}}},{"payload":{"correlation":{"metadata":{"customerId":"12345","project":"Project Two"}}}},{"payload":{"correlation":{"metadata":{"customerId":"54323","project":"Project One"}}}}]
data = Array.from(new Set(data.map(f => f.payload.correlation.metadata.project))).map(d => {
return {
[d]: [...new Set(data.filter(f => f.payload.correlation.metadata.project === d).map(c => c.payload.correlation.metadata.customerId))].length
}
});
console.log(data);
CodePudding user response:
Use the reduce method in combination with an array of unique ids for each project, then use length on those array to know the final count.
Here is my proposition:
const arr = [
{
"payload":{
"correlation":{
"metadata":{
"customerId":"12345",
"project":"Project One"
}
}
}
},
{
"payload":{
"correlation":{
"metadata":{
"customerId":"12345",
"project":"Project Two"
}
}
}
},
{
"payload":{
"correlation":{
"metadata":{
"customerId":"12345",
"project":"Project Two"
}
}
}
},
{
"payload":{
"correlation":{
"metadata":{
"customerId":"54323",
"project":"Project One"
}
}
}
}
]
const cb = (accumulator, { payload }) => {
const { project, customerId } = payload.correlation.metadata
if (!accumulator[project]) {
return { ...accumulator, [project]: [customerId] }
}
else if (accumulator[project] && accumulator[project].indexOf(customerId) === -1) {
return { ...accumulator, [project]: [...accumulator[project], customerId] }
} else return accumulator
}
const initialAccumulator = {}
const result1 = arr.reduce(cb, initialAccumulator)
const result2 = Object.keys(result1).map(key => ({ [key]: result1[key].length }))
console.log(result2)