I have an array of javascript objects that are products. These products are displayed in a list as a cart.
I want to count the number of duplicate products in the ar
You can make use of array.reduce
method to convert an original array into a new array with desired structure.
We can just check if the id exists in the array and accordingly update the array with new object having count property.
let arr = [{
id: 1
}, {
id: 1
}, {
id: 1
}, {
id: 2
}, {
id: 2
}];
let new_arr = arr.reduce((ar, obj) => {
let bool = false;
if (!ar) {
ar = [];
}
ar.forEach((a) => {
if (a.id === obj.id) {
a.count++;
bool = true;
}
});
if (!bool) {
obj.count = 1;
ar.push(obj);
}
return ar;
}, []);
console.log(new_arr);
The easiest would be probably a map:
var map=new Map();
names.forEach(function(el){
if(map.has(el["_id"])){
map.get(el["_id"]).count++;
}else{
map.set(el["_id"],Object.assign(el,{count:1}));
}
});
And then recreate an array:
names=[...map.values()];
Or in old hash/array way:
var hash={},result=[];
names.forEach(function(name){
var id=name["_id"];
if(hash[id]){
hash[id].count++;
}else{
result.push(hash[id]={
count:1,
...name
});
}
});
console.log(result);
I would stick to reduce
, use a Map
and spread its values
to get the final result:
const names = [{ _id: 1 }, { _id: 1}, { _id: 2}, { _id: 1}];
const result = [...names.reduce( (mp, o) => {
if (!mp.has(o._id)) mp.set(o._id, { ...o, count: 0 });
mp.get(o._id).count++;
return mp;
}, new Map).values()];
console.log(result);
Or you can first create all the keys in the map with a zero count (using the Map constructor), and then iterate the data again to update the counter. This split of tasks makes the code more concise than with reduce
:
const names = [{ _id: 1 }, { _id: 1}, { _id: 2}, { _id: 1}];
const mp = new Map(names.map(o => [o._id, {...o, count: 0 }]));
for (const {_id} of names) mp.get(_id).count++;
const result = Array.from(mp.values());
console.log(result);
When you would have more than one key, then one idea is to join those with JSON.stringify([ ])
:
const names = [{cat: 1, sub: 1}, {cat: 1, sub: 2}, {cat: 2, sub: 1}, {cat: 1, sub: 1}];
const result = [...names.reduce( (mp, o) => {
const key = JSON.stringify([o.cat, o.sub]);
if (!mp.has(key)) mp.set(key, { ...o, count: 0 });
mp.get(key).count++;
return mp;
}, new Map).values()];
console.log(result);