I'm trying to reduce an array, and transform it in multiple array.
const array = [
{ a: 1, b: 6 },
{ a: 1, b: 5 },
{ a: 1, b: 6 },
{ a: 1, b: 4 },
{ a: 1, b: 5 }
];
var newArray = array.reduce(
(memo, curr) => {
memo.forEach((item, key) => {
const found = item.filter((el) => el.a === curr.a && el.b === curr.b);
if (found.length > 0) return memo[key].push(curr);
else return memo.push([curr]);
});
return memo;
},
[[]]
);
The needed result I try to get is
[
[
{ a: 1, b: 5 },
{ a: 1, b: 5 }
],
[
{ a: 1, b: 6 },
{ a: 1, b: 6 },
],
[
{ a: 1, b: 4 },
]
];
But as you can see if you try, because I push on the memo, the loop continue to fire. And the result contain hundreds arrays.
How I'm supposed to do to limit this loop and get the right result ?
Thanks a lot in advance :)
CodePudding user response:
You could use Map
to group the element by the key of {a, b}
, and then get the values of the group
const array = [
{ a: 1, b: 6 },
{ a: 1, b: 5 },
{ a: 1, b: 6 },
{ a: 1, b: 4 },
{ a: 1, b: 5 },
];
var newArray = Array.from(
array
.reduce((map, curr) => {
const key = JSON.stringify({ a: curr.a, b: curr.b });
if (!map.has(key)) {
map.set(key, []);
}
map.get(key).push(curr);
return map;
}, new Map())
.values()
);
console.log(newArray);
CodePudding user response:
Look at your code. You have a triple nested loop, which is insane and definitely not needed to achieve this. Why not use a map?
Here is a function that will do what you want to do with any array of objects given.
const array = [
{ a: 1, b: 6 },
{ a: 1, b: 5 },
{ a: 1, b: 6 },
{ a: 1, b: 4 },
{ a: 1, b: 5 },
];
const separate = (arr) => {
const reduced = arr.reduce((acc, curr) => {
const path = JSON.stringify(curr);
if (!acc[path]) acc[path] = [];
acc[path].push(curr);
return acc;
}, {});
return Object.values(reduced);
};
console.log(separate(array));
CodePudding user response:
If you push inside for loop it will going to push for every reduce function iteration also.
you can achieve by adding some local variables like here
const array = [
{ a: 1, b: 6 },
{ a: 1, b: 5 },
{ a: 1, b: 6 },
{ a: 1, b: 4 },
{ a: 1, b: 5 }
];
// shift changes the orginal array
// it will remove and return firstElement
var firstElement = array.shift(1);
var newArray = array.reduce(
(memo, curr) => {
let isFound = false;
let index = 0;
memo.forEach((item, key) => {
const found = item.filter((el) => el.a === curr.a && el.b === curr.b);
if(found.length > 0){
index = key;
isFound = true;
return;
}
});
if(isFound) {
memo[index].push(curr);
} else {
memo.push([curr]);
}
return memo;
},
[[firstElement]]
);
console.log(newArray);