Sharanjeet Singh
Sharanjeet Singh

Reputation: 89

Find only the minimum Object having value Price and grouping by Category (JavaScript)

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

Answers (2)

score30
score30

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:

  1. Sort the fruits array based on each item's price
  2. Create a result empty object and loop through sorted fruits
  3. If the result object DOES NOT have a key of each fruit's name: We will push that fruit object into result object

Here 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

Kinglish
Kinglish

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

Related Questions