Reputation: 89
I have an array of objects like this:
const fruits =
[
{ id: 1, fruit: "apple", store: "store1", price: 1 }
, { id: 2, fruit: "apple", store: "store2", price: 1.25 }
, { id: 3, fruit: "banana", store: "store1", price: 0.5 }
, { id: 4, fruit: "banana", store: "store2", price: 0.75 }
, { id: 5, fruit: "Orange", store: "store3", price: 5 }
, { id: 6, fruit: "Orange", store: "store1", price: 5.1 }
, { id: 7, fruit: "Cherry", store: "store1", price: .1 }
, { id: 8, fruit: "Cherry", store: "store1", price: .6 }
, { id: 9, fruit: "", store: "store1", price: 0.5 }
]
Now, I want to group them by category in ascending order which I am able to do with the following approach:
const groupBy = (fruits.sort((a, b) => a.price - b.price)).reduce((grouped, object) => {
let x = object["fruit"]
if (!grouped[x]) {
grouped[x] = []
}
grouped[x].push(object)
return grouped
}, [])
Output of above code is as expected:-
"": [{…}]
Cherry: (2) [{…}, {…}]
Orange: (2) [{…}, {…}]
apple: (2) [{…}, {…}]
banana: (2) [{…}, {…}]
Now (issue), I only want the object that has the minimum price for that category. I tried something like the below code but the output is the same as the above code:
const groupBy = (fruits.sort((a, b) => a.price - b.price)).reduce((grouped, object) => {
let x = object["fruit"]
if (!grouped[x]) {
grouped[x] = []
}
else if (grouped[x]?.price < object?.price) {
let c = grouped[x]
return grouped[x]
}
grouped[x].push(object)
return grouped
}, [])
Upvotes: 2
Views: 106
Reputation: 304
Because you are already sorting based on different items price, you can simply only push to array if (!grouped[x])
. Please see it here:
const fruits = [
{ id: 1, fruit: 'apple', store: 'store1', price: 1 },
{ id: 2, fruit: 'apple', store: 'store2', price: 1.25 },
{ id: 3, fruit: 'banana', store: 'store1', price: 0.5 },
{ id: 4, fruit: 'banana', store: 'store2', price: 0.75 },
{ id: 5, fruit: 'Orange', store: 'store3', price: 5 },
{ id: 6, fruit: 'Orange', store: 'store1', price: 5.1 },
{ id: 7, fruit: 'Cherry', store: 'store1', price: 0.1 },
{ id: 8, fruit: 'Cherry', store: 'store1', price: 0.6 },
{ id: 9, fruit: '', store: 'store1', price: 0.5 },
];
const groupBy = fruits
.sort((a, b) => a.price - b.price)
.reduce((grouped, object) => {
let x = object['fruit'];
if (!grouped[x]) {
grouped[x] = [];
grouped[x].push(object);
}
return grouped;
}, []);
console.log(groupBy);
--- UPDATE ---
Another solution that I think is a bit cleaner than the reduce
function would be to:
fruits
array based on each item's priceHere is the code:
const result = {};
fruits
.sort((a, b) => a.price - b.price)
.forEach((item) => {
if (!(item.fruit in result)) {
result[item.fruit] = item;
}
});
console.log(result);
Upvotes: 1
Reputation: 23654
Not sure why you were creating an array - it looks like what you want is an object. To find the minimum price you can use Math.min
. Note that I use some shorthand to compare:
...
grouped[x] = Math.min(grouped[x] ?? 10000, object.price)
...
Which basically says 'If there isn't a current price, use 10000'
const fruits = [
{ id: 1, fruit: 'apple', store: 'store1', price: 1 },
{ id: 2, fruit: 'apple', store: 'store2', price: 1.25 },
{ id: 3, fruit: 'banana', store: 'store1', price: 0.5 },
{ id: 4, fruit: 'banana', store: 'store2', price: 0.75 },
{ id: 5, fruit: 'Orange', store: 'store3', price: 5 },
{ id: 6, fruit: 'Orange', store: 'store1', price: 5.1 },
{ id: 7, fruit: 'Cherry', store: 'store1', price: 0.1 },
{ id: 8, fruit: 'Cherry', store: 'store1', price: 0.6 },
{ id: 9, fruit: '', store: 'store1', price: 0.5 },
];
const groupBy = fruits.reduce((grouped, object) => {
let x = object["fruit"];
if(x.trim()=="") return grouped;
grouped[x] = Math.min(grouped[x] ?? Infinity, object.price)
return grouped;
}, {})
console.log(groupBy)
Upvotes: 0