Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Array.reduce
Tracy Gilmore
Tracy Gilmore

Posted on • Edited on

     

Array.reduce

Why is the sea salty? Simple question but stay with me because I think the water cycle is a good analogy for the wayreduce method really works.

In short, water (H2O) evaporates from the surface of the oceans to form clouds. The clouds pass over land and condense until they start to precipitate as rain/snow fall. Eventually the falling water runs into rivers and starts on it way to the sea. En route the water picks up minerals including salts and carries them to the sea. As the cycle starts again the minerals are left behind and over time concentration levels build.

To see how the water cycle can help us understand the wayreduce works we have to break it down into three element:

  • The minerals equate to the items in the array on which we are performing thereduce.
  • The water is the accumulator parameter or the reducer callback function.
  • The ocean is the accumulator in its argument form, both in the initial and final values.

So let's align this to code

Please excuse the concentration measurements, they are probably way off, I am not a chemist.

First we will prepare some test data. The following code generates simulated samples, two per month for a years.

constmineralsPerCycle=concentrationSamplesOverYear(24);console.table(mineralsPerCycle);functionconcentrationSamplesOverYear(samples){constinterval=(2*Math.PI)/samples;constcaptureSample=i=>((Math.random()+7)/8)*((Math.cos(i*interval)+2)/3);return[...newArray(samples)].map((_,i)=>captureSample(i));}
Enter fullscreen modeExit fullscreen mode

Theconsole.table will render the values before we use them. Below is an example but yours will have different values.

┌─────────┬─────────────────────┐│ (index) │       Values        │├─────────┼─────────────────────┤│    0    │  0.89801916280756   ││    1    │ 0.9567662790947499  ││    2    │ 0.9325939089002321  ││    3    │ 0.8992754278881672  ││    4    │ 0.7532231143389726  ││    5    │ 0.6765845269058688  ││    6    │ 0.6187743088061717  ││    7    │ 0.5157538308846997  ││    8    │ 0.46555646525988514 ││    9    │ 0.38054565223528175 ││   10    │ 0.33107496732400704 ││   11    │ 0.3348125096349211  ││   12    │ 0.30271050596599436 ││   13    │ 0.30352471441053985 ││   14    │ 0.3696661578004031  ││   15    │ 0.4156042590776569  ││   16    │ 0.4608111994637522  ││   17    │  0.53172225574472   ││   18    │ 0.6594949154650602  ││   19    │ 0.6714790771824638  ││   20    │ 0.7728233018044018  ││   21    │ 0.8208884212567936  ││   22    │  0.924437922104001  ││   23    │ 0.9497900622814304  │└─────────┴─────────────────────┘
Enter fullscreen modeExit fullscreen mode

Next we will simulate the accumulation of minerals as implied by each fortnightly sample.

letoceanConcentration=0;console.log(`Initial concentration =${oceanConcentration} mgs/ltr`);oceanConcentration=mineralsPerCycle.reduce(waterCycle,oceanConcentration);console.log(`Final concentration =${oceanConcentration} mgs/ltr`);functionwaterCycle(currentConcentration,cycleConcentration){returncurrentConcentration+cycleConcentration;}/* OutputInitial concentration = 0 mgs/ltrFinal concentration = 14.945932946637733 mgs/ltr*/
Enter fullscreen modeExit fullscreen mode

Note in the above code how we have simplified the calling of the reduce method by firstly referencing the callback function and secondly referencing a variable for the initial value of the accumulator.

functionwaterCycle(currentConcentration,cycleConcentration){constnewConcentration=currentConcentration+cycleConcentration;console.log(`${cycleConcentration} +${currentConcentration} =${newConcentration}`);returnnewConcentration;}
Enter fullscreen modeExit fullscreen mode

If we replace the waterCycle reducer for the above version we can see the concentration 'accumulate' with each sample.

0.89801916280756 + 0 = 0.898019162807560.9567662790947499 + 0.89801916280756 = 1.854785441902310.9325939089002321 + 1.85478544190231 = 2.7873793508025420.8992754278881672 + 2.787379350802542 = 3.6866547786907090.7532231143389726 + 3.686654778690709 = 4.4398778930296810.6765845269058688 + 4.439877893029681 = 5.116462419935550.6187743088061717 + 5.11646241993555 = 5.7352367287417220.5157538308846997 + 5.735236728741722 = 6.25099055962642150.46555646525988514 + 6.2509905596264215 = 6.7165470248863070.38054565223528175 + 6.716547024886307 = 7.0970926771215880.33107496732400704 + 7.097092677121588 = 7.4281676444455950.3348125096349211 + 7.428167644445595 = 7.7629801540805160.30271050596599436 + 7.762980154080516 = 8.065690660046510.30352471441053985 + 8.06569066004651 = 8.3692153744570490.3696661578004031 + 8.369215374457049 = 8.7388815322574520.4156042590776569 + 8.738881532257452 = 9.1544857913351090.4608111994637522 + 9.154485791335109 = 9.615296990798860.53172225574472 + 9.61529699079886 = 10.147019246543580.6594949154650602 + 10.14701924654358 = 10.8065141620086410.6714790771824638 + 10.806514162008641 = 11.4779932391911060.7728233018044018 + 11.477993239191106 = 12.2508165409955080.8208884212567936 + 12.250816540995508 = 13.0717049622523010.924437922104001 + 13.071704962252301 = 13.9961428843563030.9497900622814304 + 13.996142884356303 = 14.945932946637733
Enter fullscreen modeExit fullscreen mode

Unsurprisingly the callback function of the reduce method (parameter one) is called a reducer. However, one thing that confuses matters is that the callback is not called a reducer because it 'reduces' an array of (potentially) many items into a single value (it might not). It is called a reducer because (for each element of the array) it takes two arguments (primarily, we will expand on this point later) the accumulator and the element. It then reduces them to a single value to form the new accumulator.

On the point of how many parameters theArray.reduce method expects, it actually expects up to four:

  1. The accumulator - the in-bound reduced value
  2. The item - the element from the array to be reduced
  3. The index of the element of the array (not often used)
  4. The array being processed (not reduced), very rarely used.

We will explore the fact the output might not be a single value in the next section.

Reduce, the root of many methods

Thereduce method is capable of many operations (we will explore this later) and once mastered it is easy to find opportunities to use it but there are usually better options.

Themap method

Likereduce themap method takes a callback but in this case it is a mapping function that takes a value from the array and produces a new value, one for one. The new array that is created will be the same size as the input array.

If we usemap in the following fashion,

functioncelsiusToFahrenheit(degCelsius){return(degCelsius*9)/5+32;}console.table([-40,0,16,100].map(celsiusToFahrenheit));
Enter fullscreen modeExit fullscreen mode

a table of temperatures in Fahrenheit will be presented on the console for each of the Celsius temperatures in the input array.
This can also be written using thereduce method as follows using the same mapping function.

console.table([-40,0,16,100].reduce((acc,celsius)=>[...acc,celsiusToFahrenheit(celsius)],[]));
Enter fullscreen modeExit fullscreen mode

Thefilter method

We can do something similar to reproduce thefilter method using a predicate function such as:

constgreaterThanFifty=(value)=>value>50;console.table([20,40,60,80,100].filter(greaterThanFifty));// 60, 80, 100
Enter fullscreen modeExit fullscreen mode

Now with thereduce method.

console.table([20,40,60,80,100].reduce((acc,val)=>greaterThanFifty(val)?[...acc,val]:acc,[]));
Enter fullscreen modeExit fullscreen mode

In both examples usingreduce make for a longer and slightly more complicated solution. However,reduce can combine both operations in a single pass.

console.table([-40,0,16,100].reduce((acc,celsius)=>{constfahrenheit=celsiusToFahrenheit(celsius);returngreaterThanFifty(fahrenheit)?[...acc,fahrenheit]:acc;},[]));// [60.8, 212]
Enter fullscreen modeExit fullscreen mode

In fact the output of areduce does not even have to be an array.

console.table([-40,0,16,100].reduce((acc,celsius)=>({...acc,[celsius]:celsiusToFahrenheit(celsius)}),{}));// {'16': 60.8, '100': 212}
Enter fullscreen modeExit fullscreen mode

The above example will produce an object containing a mapping of the Celsius to Fahrenheit temperatures but only for those Fahrenheit temperatures greater than 50 degrees.

Do's and Don'ts

In this final section I would like to offer some advice for using thereduce method.

Do's

  1. Usereduce when converting from an array to another data structure.
  2. Consider using thereduce method when the operation is a combination ofmapping andfiltering.

Don'ts

  1. Do not usereduce when there are better alternative methods. They well usually perform better as they are implemented within the JavaScript engine.
  2. Don't be scared to at least explore using thereduce method when appropriate.

Reduce's evil twin

Thereduce method is not likely to be a method you use every day but knowing it exists and what is capable of adds another tool to your toolbox.

An even less used array method in reduce's (not so) evil twinreduceRight, which I think is fairly obvious what it does.Reduce processes the items in the array from left to right (in index order),reduceRight processes the array from right to left (in inverse index order). ButreduceRight is not equivalent toArray.reverse().reduce() because the third parameter of the reducer function will decrease not increase as the method traverses the array.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

After my first contact with a computer in the 1980's, I taught myself to program in BASIC and Z80 assembler. I went on to study Computer Science and have enjoyed a long career in Software Engineering.
  • Location
    Somerset, UK
  • Education
    BSc (Hons) Computer Science
  • Work
    Software Engineer specialising in web technologies, frontend and full stack (Node & xAMPP)
  • Joined

More fromTracy Gilmore

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp