0

I have one array which is named as tiers and one quantity variable. Now I am trying to get the matched range value from my tier array. Based on the matched result I want to calculate the discount. I tried to with find method but it gives me an unexpected ouput.

Actual output {id: 1, discount_percent:0, quantity:6, title:"Tier 1"}

Expeceted Output {id: 3, discount_percent:10, quantity:10, title:"Tier 3"}

let tiers = [
   {id: 1, discount_percent:0, quantity:6, title:"Tier 1"},
   {id: 2, discount_percent:5, quantity:8, title:"Tier 2"},
   {id: 3, discount_percent:10, quantity:10, title:"Tier 3"},
   {id: 4, discount_percent:12, quantity:12, title:"Tier 4"},
   {id: 5, discount_percent:14, quantity:14, title:"Tier 5"},
   {id: 6, discount_percent:20, quantity:16, title:"Tier 6"},
   {id: 7, discount_percent:40, quantity:18, title:"Tier 7"},
   {id: 8, discount_percent:50, quantity:50, title:"Tier 8"},
]
function calculateDiscount(){
   const ordersQuanity = 10;
   const tier = tiers.find((_tier) => _tier.quantity <= ordersQuanity);
   ...
}
1
  • _tier.quantity <= ordersQuanity this should be _tier.quantity >= ordersQuanity You need to find the first object where quantity is greater than or equal to given threshold Commented Jan 6, 2023 at 6:03

2 Answers 2

1

For the generic situation of a number of objects with discount_percents and quantitys, .find isn't the right approach because it'll stop as soon as it finds a match. Consider .reduce instead - if an element being iterated over passes the test and it has a greater discount_percent than the current element in the accumulator (if there's anything in the accumulator to begin with), return it instead.

let tiers = [
   {id: 1, discount_percent:0, quantity:6, title:"Tier 1"},
   {id: 2, discount_percent:5, quantity:8, title:"Tier 2"},
   {id: 3, discount_percent:10, quantity:10, title:"Tier 3"},
   {id: 4, discount_percent:12, quantity:12, title:"Tier 4"},
]
function calculateDiscount(){
   const ordersQuanity = 10;
   const bestTier = tiers.reduce((a, tier) => (
     tier.quantity <= ordersQuanity && (!a || tier.discount_percent > a.discount_percent)
       ? tier
       : a
   ), null) || tiers[0]; // alternate with the first element of the array
   // if you want to default to that tier even if the quantity isn't sufficient
   console.log(bestTier);
}
calculateDiscount();

If you happen to be able to assume that every increased discount_percent comes with a larger quantity, and the array is sorted, you can use .find if you reverse the array first (so that the items with the greatest discount_percent are iterated over first).

let tiers = [
   {id: 1, discount_percent:0, quantity:6, title:"Tier 1"},
   {id: 2, discount_percent:5, quantity:8, title:"Tier 2"},
   {id: 3, discount_percent:10, quantity:10, title:"Tier 3"},
   {id: 4, discount_percent:12, quantity:12, title:"Tier 4"},
];
const tiersReversed = [...tiers].reverse();
function calculateDiscount(){
   const ordersQuanity = 10;
   const tier = tiersReversed
     .find((_tier) => _tier.quantity <= ordersQuanity)
      || tiers[0]; // alternate with the first element of the array
   // if you want to default to that tier even if the quantity isn't sufficient
   console.log(tier);
}
calculateDiscount();

The snippet works just as well for the dataset in the edited question.

let tiers = [
   {id: 1, discount_percent:0, quantity:6, title:"Tier 1"},
   {id: 2, discount_percent:5, quantity:8, title:"Tier 2"},
   {id: 3, discount_percent:10, quantity:10, title:"Tier 3"},
   {id: 4, discount_percent:12, quantity:12, title:"Tier 4"},
   {id: 5, discount_percent:14, quantity:14, title:"Tier 5"},
   {id: 6, discount_percent:20, quantity:16, title:"Tier 6"},
   {id: 7, discount_percent:40, quantity:18, title:"Tier 7"},
   {id: 8, discount_percent:50, quantity:50, title:"Tier 8"},
]
function calculateDiscount(ordersQuanity){
   const bestTier = tiers.reduce((a, tier) => (
     tier.quantity <= ordersQuanity && (!a || tier.discount_percent > a.discount_percent)
       ? tier
       : a
   ), null) || tiers[0]; // alternate with the first element of the array
   // if you want to default to that tier even if the quantity isn't sufficient
   console.log(bestTier);
}
calculateDiscount(10);
calculateDiscount(20);

Sign up to request clarification or add additional context in comments.

6 Comments

both of the approaches are working, but if the quantity is less then any tier quantity then it returns null or undefined. Please check with const ordersQuanity = 5. In that case what should I do? please suggest?
Yes, that's what your data would seem to indicate the expected output would be. If the threshold for the lowest tier is quantity: 6, then quantity: 5 will not pass any thresholds.
In that case, if does not match any tier I want the first tier to be returned, is there any way I can return the first tier within the reduce or find method?
I'd move the condition outside. eg .reduce(...) || tiers[0]
I am reopening the issue because, if the quantity is 20 then the solutions are not working.
|
0

`function discountPercent(item){ return item.discount_percent == 10 }

console.log(tiers.find(discountPercent))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.