Reputation: 5172
I want to simplify and get last part missing.
So, I have an array of objects like:
const data = [{
"company": "aaa",
"qty": 1,
"id": 1
}, {
"company": "bbb",
"qty": 14,
"id": 2
}, {
"company": "ccc",
"qty": 2,
"id": 3
}, {
"company": "ddd",
"qty": 5,
"id": 4
},
{
"company": "eee",
"qty": 55,
"id": 5
}
];
I need to add the percentage based on qty
and overall create a new object with detail of only companies with percentage greater than "X" (let's say 10) and others merged in a "other companies", like a similar
{
"idCompany": 2,
"name": "bbb",
"percentage": 18.181818181818183,
"qty": 14
},{
"idCompany": 5,
"name": "eee",
"percentage": 71.42857142857143,
"qty": 55
},{
"idCompany": null,
"name": "others",
"percentage": 10.391 // 100 - 71.42xxx - 18.18
"qty": 8 // 1 + 2 + 5
},
So, my steps:
const total = data.reduce((i, el) => i+el.qty, 0);
let rawData = data.map(el => {
return {
name: el.company,
qty: el.qty,
idCompany: el.id,
percentage: (el.qty/total)*100,
}
})
let consolidateCompanies = rawData.filter(el => el.percentage > 10);
But...
Now, how can I get the OTHERS companies and add to the consolidateCompanies
object? And with a more beautiful code?
const data = [{
"company": "aaa",
"qty": 1,
"id": 1
}, {
"company": "bbb",
"qty": 14,
"id": 2
}, {
"company": "ccc",
"qty": 2,
"id": 3
}, {
"company": "ddd",
"qty": 5,
"id": 4
},
{
"company": "eee",
"qty": 55,
"id": 5
}
];
// Get the total
const total = data.reduce((i, el) => i+el.qty, 0);
// Add percentage to the objects
let rawData = data.map(el => {
return {
name: el.company,
qty: el.qty,
idCompany: el.id,
percentage: (el.qty/total)*100,
}
})
// Get only companies that have percentage greater than 10
let consolidateCompanies = rawData.filter(el => el.percentage > 10);
console.log(consolidateCompanies);
// But I'm missing 1, 3 and 4
Upvotes: 0
Views: 73
Reputation: 1182
Use forEach instead of map and filter, and loop the Object with your required need as follows.
const minPerc =10;
const data = [{
"company": "aaa",
"qty": 1,
"id": 1
}, {
"company": "bbb",
"qty": 14,
"id": 2
}, {
"company": "ccc",
"qty": 2,
"id": 3
}, {
"company": "ddd",
"qty": 5,
"id": 4
},
{
"company": "eee",
"qty": 55,
"id": 5
}
];
// Get the total
const total = data.reduce((i, el) => i+el.qty, 0);
let consolidateCompanies = [];
let otherObj={"idCompany": null,
"name": "others",
"percentage": 0,
"qty": 0};
data.forEach(ele=>{
let perc=(ele.qty/total)*100;
if(perc>minPerc){
consolidateCompanies.push({...ele,...{percentage:perc}})
}else{
otherObj.qty +=ele.qty; otherObj.percentage+=perc
} });
consolidateCompanies.push(otherObj);
console.log(consolidateCompanies);
Upvotes: 0
Reputation: 386868
You could seperate others
and add only if necessary without grouping by usining another object.
const
data = [{ company: "aaa", qty: 1, id: 1 }, { company: "bbb", qty: 14, id: 2 }, { company: "ccc", qty: 2, id: 3 }, { company: "ddd", qty: 5, id: 4 }, { company: "eee", qty: 55, id: 5 }],
totalQty = data.reduce((t, { qty }) => t + qty, 0),
others = { idCompany: null, name: "others", percentage: 0, qty: 0 },
result = data.reduce((r, { company: name, qty, id: idCompany }) => {
const percentage = qty * 100 / totalQty;
if (percentage >= 10) {
r.push({ idCompany, name, percentage, qty });
} else {
others.qty += qty;
others.percentage = others.qty * 100 / totalQty;
}
return r;
}, []);
if (others.qty) result.push(others);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 30725
You could do this with a couple of Array.reduce()
calls.
We'd group companies either by name or 'others', adding percentage and quantity for the others.
const data = [{ "company": "aaa", "qty": 1, "id": 1 }, { "company": "bbb", "qty": 14, "id": 2 }, { "company": "ccc", "qty": 2, "id": 3 }, { "company": "ddd", "qty": 5, "id": 4 }, { "company": "eee", "qty": 55, "id": 5 } ];
const total = data.reduce((i, el) => i+el.qty, 0);
const minPercentage = 10;
const consolidateCompanies = Object.values(data.reduce((acc, el) => {
const percentage = (el.qty/total)*100;
const name = (percentage >= minPercentage) ? el.company: 'others';
const id = (percentage >= minPercentage) ? el.id: null;
acc[name] = acc[name] || { name, percentage: 0, qty: 0, id };
acc[name].percentage += percentage;
acc[name].qty += el.qty;
return acc;
}, {}))
console.log(consolidateCompanies);
.as-console-wrapper { max-height: 100% !important; }
Upvotes: 1
Reputation: 648
here is the refactor of your code
const data = [{
"company": "aaa",
"qty": 1,
"id": 1
}, {
"company": "bbb",
"qty": 14,
"id": 2
}, {
"company": "ccc",
"qty": 2,
"id": 3
}, {
"company": "ddd",
"qty": 5,
"id": 4
},
{
"company": "eee",
"qty": 55,
"id": 5
}
];
const total = data.reduce((i, el) => i+el.qty, 0)
const startWith = [{
"idCompany": null,
"name": "others",
"percentage": 0,
"qty": 0
}]
let rawData = data.reduce((acc, value) => {
// console.log('value', value)
const withPercentage = {
name: value.company,
qty: value.qty,
idCompany: value.id,
percentage: (value.qty/total)*100,
}
if (withPercentage.percentage > 10) {
acc.push(withPercentage)
} else {
acc[0].qty += withPercentage.qty;
acc[0].percentage += withPercentage.percentage;
}
return acc;
}, startWith).filter(f => f.percentage !== 0 && f.qty !== 0);
console.log(rawData)
Upvotes: 0