This is my array of objects:
const cart = [
{ group: "group 1", qtd: 12, value: 65, term: 20 }, //index 0
{ group: "group 1", qtd: 10, value: 100, term: 20 }, //index 1
{ group: "group 1", qtd: 18, value: 40, term: 10 }, //index 2
{ group: "group 2", qtd: 5, value: 30, term: 25 }, //index 3
{ group: "group 2", qtd: 22, value: 10, term: 25 }, //index 4
{ group: "group 3", qtd: 6, value: 60, term: 12 } //index 5
];
And I need to do some treatments to get this output:
result = [
{ group: "group 1", value: 1780, term: 20 },
{ group: "group 1", value: 720, term: 10 },
{ group: "group 2", value: 370, term: 25 },
{ group: "group 3", value: 360, term: 12 }
];
If the group is equal and the term is equal too, I need to add the qtd and the value of the indexes that matches with this rule. In this exemple, index 0 and 1 matches with the rule, so I make (12 * 65) (10 * 100) = 1780 | index 3 and 4 matches too, so I make (5 * 30) (22 * 10) = 370. And if the terms doesn't match, I just sum like in the other cases and show separately, like in indexes 2 and 5.
First i was trying to get the distinct elements of this object and how much times and how many times did it repeat itself, so I use lodash for this:
const counts = _.countBy(cart, "group");
And the output:
{ 'group 1': 3, 'group 2': 2, 'group 3': 1 }
And from that logic I can't think of a solution
I already try I lot of logics but I can't get anywhere, I would be very grateful if someone could help me in this logic.
CodePudding user response:
Here's one way. Use array.reduce as an iterator, then create a sort of temporary ID to track according to your requirements - the id combines the group name and the term. So the iterator keeps a record of the objects like {"group 1_20" : { ...data}
so you can easily find a matching set of values to add together the numbers. Finally, remove those temporary ID keys with Object.values()
const cart = [
{ group: "group 1", qtd: 12, value: 65, term: 20 }, //index 0
{ group: "group 1", qtd: 10, value: 100, term: 20 }, //index 1
{ group: "group 1", qtd: 18, value: 40, term: 10 }, //index 2
{ group: "group 2", qtd: 5, value: 30, term: 25 }, //index 3
{ group: "group 2", qtd: 22, value: 10, term: 25 }, //index 4
{ group: "group 3", qtd: 6, value: 60, term: 12 } //index 5
];
const result = Object.values(cart.reduce((b, a) => {
let iden = a.group "_" a.term;
if (b[iden]) {
b[iden] = { ...b[iden],
value: b[iden].value (a.qtd * a.value)
}
} else {
a.value = a.qtd * a.value;
delete a.qtd;
b[iden] = a;
}
return b;
}, {}))
console.log(result)
CodePudding user response:
You could group by the wanted keys and take an object for grouping. At result take the values of the object.
const
cart = [{ group: "group 1", qtd: 12, value: 65, term: 20 }, { group: "group 1", qtd: 10, value: 100, term: 20 }, { group: "group 1", qtd: 18, value: 40, term: 10 }, { group: "group 2", qtd: 5, value: 30, term: 25 }, { group: "group 2", qtd: 22, value: 10, term: 25 }, { group: "group 3", qtd: 6, value: 60, term: 12 }],
keys = ['group', 'term'],
result = Object.values(cart.reduce((r, { qtd, value, ...o }) => {
const key = keys.map(k => o[k]).join('|');
r[key] ??= { ...o, value: 0 };
r[key].value = qtd * value;
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
const cart = [
{ group: "group 1", qtd: 12, value: 65, term: 20 }, //index 0
{ group: "group 1", qtd: 10, value: 100, term: 20 }, //index 1
{ group: "group 1", qtd: 18, value: 40, term: 10 }, //index 2
{ group: "group 2", qtd: 5, value: 30, term: 25 }, //index 3
{ group: "group 2", qtd: 22, value: 10, term: 25 }, //index 4
{ group: "group 3", qtd: 6, value: 60, term: 12 } //index 5
];
const result = Object.values(cart.reduce((acc, el) => {
const key = el.group "_" el.term;
if (!acc[key]) acc[key] = {group: el.group, term: el.term, value: 0};
acc[key].value = el.qtd * el.value;
return acc;
}, {}));
console.log(result);