Kasper Juner
Kasper Juner

Reputation: 952

How to return two values in .reduce?

I have a function which count the total of the cart and the quantity of items inside it, the function is called every time an item has changed or a new one has been added.

I was looking for the best way to achieve the counting of total and quantity in one function, for now the function looks like this:

  cartTotal(): void{
    this.carrello.totale = this.carrello.plu.reduce((total, item) => {
      return total + (item.prezzo * item.qta);
    }, 0);
    const count = this.carrello.plu.reduce((qta, item) => {
      return qta + (item.qta);
    }, 0);

    this.cartCount.next(count);
  }

But i would reduce the function to only one .reduce so i've tryed the following solution:

  cartTotal(): void{
    let count = 0;
    this.carrello.totale = this.carrello.plu.reduce((total, item) => {
      count += item.qta;
      return total + (item.prezzo * item.qta);
    }, 0);

    this.cartCount.next(count);
  }

But the last one does not convince me, so i was wondering which would be the best solution to it..

Upvotes: 3

Views: 10409

Answers (3)

Oz Harb
Oz Harb

Reputation: 1

Here's a cool way to return two values using reduce(). This function uses reduce() to return one array with two calculated values. The first value is the sum of all of the odd elements in the passed-in array, and the second value is the sum of all of the even elements.

alternatingSums = array => array.reduce((accumulator,value,i) => { 
 
//  if the index of the passed-in array is odd then add the value to the
//  the first element of the accumulator array
//  otherwise add it to the second element of the array

  accumulator[i%2]+=value; 
  return accumulator}, [0,0])

alternatingSums([20, 10, 30, 15, 5]) // =>[ 55, 25 ]

It's technically one value because it's one array, but you're getting two values in that one array.

Upvotes: 0

Jörg W Mittag
Jörg W Mittag

Reputation: 369468

You cannot return two values in reduce. Period. In fact, this has nothing to do with reduce. You cannot return two values at all in ECMAScript (or TypeScript).

There are languages with multiple return values (Go, for example) but ECMAScript / TypeScript is not one of those languages.

However, ECMAScript does have multiple ways of bundling multiple values into one value: collections (arrays, maps, sets) and objects.

So, while you cannot return two values, you can return a collection (or an object) with two values. In most languages, you would probably return a two-element array (or a tuple in TypeScript), but ECMAScript has very lightweight object literals, so let's use that:

cartTotal(): void {
  const { quantity, total } = this.carrello.plu.reduce(
    ({ quantity, total }, { qta, prezzo }) =>
      ({ quantity: quantity + qta, total: total + prezzo * qta }),
    { quantity: 0, total: 0 }
  );

  this.carrello.totale = total;

  this.cartCount.next(quantity);
}

The explanations for reduce are often misleading. reduce is generally explained as "you reduce the collection down to a single value", but you should never forget that the "single value" can still be as complex as you like! It can still be an array, or an object, or an array-of-arrays-of-objects-of-promises, or …

In fact, if you look at the Wikipedia page for Fold, you will find at the bottom of the page a proof that Fold (which is just the more common name for reduce) is universal, by which is meant that every iteration over a collection can be written as reduce.

Upvotes: 1

micronyks
micronyks

Reputation: 55443

You can use .reduce in following way,

cartTotal(): void{

     const {total, quantity} = this.carrello.plu.reduce((acc, item) => {   // const{total, quanity} this is Destructuring assignment

          acc.quantity += item.qta;
          acc.total = acc.total + (item.prezzo * item.qta);
      
          return acc;

    }, {total:0, quantity:0});

    this.cartCount.next(acc.quantity);  // emit whatever you want to emit.  
}

console.log('Total Price', total, 'Total Quantity', quantity);

// **********************      EXAMPLE    ************************************
const {total, quantity} = [{qta:5, prezzo: 100}, {qta:5, prezzo: 100}, {qta:5, prezzo: 100}]
.reduce((acc, result) => {
     
     acc.quantity += result.qta;
      acc.total = acc.total + (result.prezzo * result.qta);
     
      return acc;
}, {total:0, quantity:0});
    

console.log('Total Price', total, 'Total Quantity', quantity);
    

Upvotes: 6

Related Questions