Amani
Amani

Reputation: 247

How to decrement items in array Incrementally based on the given quantity in Javascript

I have this sample array of objects

   mangoes:[
      { quantity:5},
      { quantity:8},
      { quantity:13},
      { quantity:4}
    ]

When I remove x mangoes, that x should be subtracted from the first element in the array, and if that x exceed the first element then it should reduce the remained quantity in the second item in the array...and so forth.

This is to say, I need the quantity to be reduced starting from the first one in the array down to the second if it exceed, to the third etc..

For example, If I buy 2 mangoes, It should minus 2 in the first array element and the resulting mangoes array should be

   mangoes:[
      { quantity:3},
      { quantity:8},
      { quantity:13},
      { quantity:4}
    ]

On the other hand, If I would have bought 7 mangoes, it should reduce all 5 from first array element and then remove 2 mangoes from the second element...and hence the final array would be like this below

   mangoes:[
      { quantity:0},
      { quantity:6},
      { quantity:13},
      { quantity:4}
    ]

By Using Javascript, how can I achieve this?

WHAT I HAVE TRIED

I have tried like this below, It works only for the first element(case) when the x is less, but for other case it doesn't work;

var x = 2
var done = false

mangoes.forEach(function (item,i) {

  if(mangoes[i].quantity>=x && !done){
    item.quantity = mangoes[i].quantity - x
    done = true
  }

})

Upvotes: 1

Views: 1016

Answers (5)

Chase
Chase

Reputation: 3126

const takeMangoes = (num, from) => from.map(x => {
  const take = Math.min(x.quantity, num);
  num -= take;
  // Original way, keep all properties, don't mutate original
  //return {...x, quantity: x.quantity - take};
  
  // Pick from below:

  // New way 1, mutate original in place
  x.quantity = x.quantity - take;
  return x;
  // New way 2, limit to OWN properties
  return Object.getOwnPropertyNames(x).reduce((a, c) => {
    a[c] = x[c];
    if (c === 'quantity') {
      a[c] -= take;
    }
    return a;
  }, {});
}).filter(x => x.quantity > 0);

console.log(takeMangoes(2, [
  {quantity: 5},
  {quantity: 8},
  {quantity: 13},
  {quantity: 4},
]));

console.log('------------------------');

console.log(takeMangoes(7, [
  {quantity: 5},
  {quantity: 8},
  {quantity: 13},
  {quantity: 4},
]));

Upvotes: 2

Rajneesh
Rajneesh

Reputation: 5308

You can take a closure inside map and generate the desired result.

var mangoes=[ { quantity:5},{ quantity:8},{ quantity:13},{ quantity:4}];
var toReduce = 5;

var result = mangoes.map((num=>({quantity})=>(r = Math.min(quantity,num),num=num-r,({quantity:quantity-r})))(toReduce));

console.log(result);

Upvotes: 1

Michael Mishin
Michael Mishin

Reputation: 571

let x = 8;

const newMangoes = mangoes.map((mango) => {
    if (!x) return mango;
    if (x <= mango.quantity) {
        newMango =  {quantity: mango.quantity - x};
        x = 0;
        return newMango;
    } else {
        x = x - mango.quantity;
        return {quantity: 0};
    }
});

Upvotes: 1

ABGR
ABGR

Reputation: 5205

You can achieve that with forEach this way. But I wouldn't recommend it because even if a quantity is found to be greater than the value to be deducted, it will still loop through the whole item list as you can't break out of a forEach loop

  var mangoes = [
      { quantity:0},
      { quantity:6},
      { quantity:13},
      { quantity:4}
    ];

var x = 2
var done = false

mangoes.forEach(function (item,i) {

 if(item.quantity< x){
   item.quantity = 0;
   x = x- item.quantity; 
  }else{
   item.quantity = item.quantity-x;
   x=0;
  }

});
console.log(mangoes)

However, I would recommend using for..of..loop so that you could conditionally break out of the loop, i.e if the quantity is found to be greater than the ones to be deducted, just deduct and break out of the loop. There's no need of further iteration.

  var mangoes = [
      { quantity:5},
      { quantity:6},
      { quantity:13},
      { quantity:4}
    ];

var x = 1
var done = false

for(let i of mangoes){
  if(i.quantity >= x){
    i.quantity  = i.quantity -x;
    x = x - i.quantity;
    break;
  }else{
    x = x - i.quantity;
    i.quantity = 0;
  }
}

console.log(mangoes)

Upvotes: 1

DynasticSponge
DynasticSponge

Reputation: 1441

var getMangoes = function(requested){
  var remaining = requested;
  var supplied = 0;
  for(var i = 0; i < mangoes.length() && supplied < requested; i++){
    if(mangoes[i].quantity >= remaining){
      mangoes[i].quantity -= remaining;
      supplied += remaining;
    }
    else {
      remaining -= mangoes[i].quantity;
      supplied += mangoes[i].quantity;
    }
  }
  return(supplied);
};

var mangoesIWant = 13;
var mangoesIGot = getMangoes(mangoesIWant);

Upvotes: 0

Related Questions