'Javascript: How would you get the highest rated product category based on these 2 arrays
Assuming I have 2 arrays:
const products = [
{
name: 'prod1',
category: 'Meat'
},
{
name: 'prod2',
category: 'Meat'
},
{
name: 'prod3',
category: 'Dairy'
}];
const rate = [
{
name: 'prod1',
rate: 23,
},
{
name: 'prod2',
rate: 36
},
{
name: 'prod3',
rate: 50,
}];
How would you get the category that has the highest sum rate? For example, prod1 and prod2 share the same category 'Meat" and hence the rate for meat is 36 + 23 = 59.
The way I thought about it is to create an adjusted Array of products where each entry will contain the rate from the second array and then I will create a result array and push an object of category and sumRate after iterating the adjustedArray.
So if the result Array has an object with category, I would adjust the sum and add the new rate, if not I'll create a new entry with category: rate.
Can we do this in a very optimal way?
Solution 1:[1]
As the OP probably knows, canonical grouping goes like this...
const prodsByCategory = products.reduce((acc, p) => {
let cat = p.category;
if (!acc[cat]) acc[cat] = [];
acc[cat].push(p);
return acc;
}, {});
Modify this a little to add the data which will be needed to optimize.
const prodsByCategory = products.reduce((acc, p) => {
let cat = p.category;
// instead of just an array, keep an array and a total
if (!acc[cat]) acc[cat] = { products: [], totalRate: 0 };
// instead of just pushing, push and increment total with a lookup
acc[cat].products.push(p);
acc[cat].totalRate += rateForProduct(p) || 0;
return acc;
}, {});
We need a lookup for rateForProduct, like this:
const rateForProduct = product => {
return rate.find(r => r.name === product.name)?.rate || 0;
}
That should produce an object keyed by category with values that have a prop called totalRate
. Sort those entries so that the first one is maximized. Here's a demo...
const products = [{
name: 'prod1',
category: 'Meat'
},
{
name: 'prod2',
category: 'Meat'
},
{
name: 'prod3',
category: 'Dairy'
}
];
const rate = [{
name: 'prod1',
rate: 23,
},
{
name: 'prod2',
rate: 36
},
{
name: 'prod3',
rate: 50,
}
];
const rateForProduct = product => {
return rate.find(r => r.name === product.name)?.rate || 0;
}
const prodsByCategory = products.reduce((acc, p) => {
let cat = p.category;
if (!acc[cat]) acc[cat] = {
products: [],
totalRate: 0
};
acc[cat].products.push(p);
acc[cat].totalRate += rateForProduct(p);
return acc;
}, {});
const sortedEntries = Object.entries(prodsByCategory).sort((a, b) => b[1].totalRate - a[1].totalRate);
const bestEntry = {
category: sortedEntries[0][0],
rate: sortedEntries[0][1].totalRate
}
console.log(bestEntry);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | danh |