grabury
grabury

Reputation: 5579

How to filter out values from an array within an indexed list of objects?

I have an indexed list of products, and each product has a price, as well as an array of bulk prices. I want to filter out all bulk prices that are higher than the product's base price. What's the best way to do this with ES6 features like destructuring.

Here is the list of prices:

prices: {
  foo: {
   price: 160,
   bulkPricing: [
    {price: 150, minimumQuantity: 10},
    {price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}
   ]
  },
  bar: {
   price: 160,
   bulkPricing: [
    {price: 180, minimumQuantity: 10},
    {price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}
   ]
  }
 }

You can see that the first bulk price for the second product is higher than the base price so it should be removed. So the result should be:

prices: {
  foo: {
   price: 160,
   bulkPricing: [
    {price: 150, minimumQuantity: 10},
    {price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}
   ]
  },
  bar: {
   price: 160,
   bulkPricing: [
    {price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}
   ]
  }
 }

I can do it like this:

Object.entries(prices).map(([sku, product])=> { 
       return { 
         [sku]: { 
           ...product, 
           bulkPricing: product.bulkPricing.filter(bp => bp.price < product.price)
         }
       }
     }
     )

But this of course returns an array:

[ { foo: { price: 160, bulkPricing: [{price: 150, minimumQuantity: 10},
    {price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}] } },
  { bar: { price: 160, bulkPricing: [{price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}] } } ]

So I guess my question is, with the latest ES6 techniques how can I filter items in an object based on arrays within those items, and return that modified object?

Upvotes: 2

Views: 55

Answers (3)

Lior Elrom
Lior Elrom

Reputation: 20882

Another option:

ES6 & Destructuring:

Object.keys(prices).reduce((obj, key) => ({
    ...obj,
    [key]: {
        ...prices[key],
        bulkPricing: prices[key].bulkPricing
            .filter(({ price }) => price <= prices[key].price)
    }
}), {});

Note: it does not use Object.values as it's not yet widely supported in older browsers and it does not mutate the prices object.

Upvotes: 1

Ele
Ele

Reputation: 33726

Just use a forEach along with the function filter to get only those objects with the price equal to or lesser than the specific price.

let obj = {  prices: {    foo: {      price: 160,      bulkPricing: [{          price: 150,          minimumQuantity: 10        },        {          price: 140,          minimumQuantity: 20        },        {          price: 130,          minimumQuantity: 30        }      ]    },    bar: {      price: 160,      bulkPricing: [{          price: 180,          minimumQuantity: 10        },        {          price: 140,          minimumQuantity: 20        },        {          price: 130,          minimumQuantity: 30        }      ]    }  }};

Object.values(obj.prices).forEach(p => p.bulkPricing = p.bulkPricing.filter(b => b.price <= p.price));

console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370979

All you need to do is filter the bulkPricing array, creating a copy first to avoid mutation of the original object:

const prices = {
  001: {
   price: 160,
   bulkPricing: [
    {price: 150, minimumQuantity: 10},
    {price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}
   ]
  },
  002: {
   price: 160,
   bulkPricing: [
    {price: 180, minimumQuantity: 10},
    {price: 140, minimumQuantity: 20},
    {price: 130, minimumQuantity: 30}
   ]
  }
};
const newPrices = JSON.parse(JSON.stringify(prices));
Object.values(newPrices).forEach((item) => {
  const { price: basePrice, bulkPricing } = item;
  item.bulkPricing = item.bulkPricing.filter(({ price }) => price < basePrice);
});
console.log(newPrices);

Upvotes: 0

Related Questions