Higher Order Functions in Javascript: .forEach()

Higher order functions. What a fancy name right? In Javascript, functions are considered “first class citizens” because they can be passed as arguments to other functions, and can also be returned from a function. That’s a lot of functions. The power of functional programming comes into play when we explore some of the Underscore.JS methods. The most popular ones include forEach.(), map.(), filter.(), and reduce.(). These are extremely powerful and useful methods for traversing and manipulating arrays. Out of all of them, reduce is probably the most complicated one – and also the most powerful one. We’ll save that for another day.

Let’s take a look at forEach.

var each = function (collection, callback) {
   if(Array.isArray(collection)){
     for(var i=0; i < collection.length; i++) {
     callback(collection[i]);
   }
 }
 else if(typeof collection === 'object') {
   for(var j = 0, key = Object.keys(collection); i < keys.length; i++) {
   callback(collection[key]);
   }
  }
}

Here is a bare bones implementation of the forEach method. Note that we did not include index as a parameter, though it can be refactored quite easily to include it. We use a forEach when we want a projection function to act upon each element in the array. However, note that forEach does not return an array. If you do not need to directly change the elements in the array, but still want a function to act upon each element in the array, then forEach would be a good choice.

Advertisements

The dizzy world of Nested Loops

We want to write a function that will take in a value and create a diamond with a size based on of the number in the function argument.

In order to approach this problem, we should break it down into smaller pieces.

  *  
 *** 
***** <-- This will be n, the argument that we will input into the function.
 *** 
  *  
Additionally, n will also dictate the total vertical 
number of stars.

Since n represents the line size of the middle of the diamond, we should 
model the rest of our logic based on this assumption. In other words,
the beginning of our diamond should increase in size per line until 
the line reaches size n. 

Conversely, the bottom half of our diamond should decrease in size,
starting at line n. It should stop when the length of our line reaches one.

Let's take a look at a diamond with a bigger n:

We need to represent this in numbers, in order to identify any potential 
patterns that can be used to create our algorithm. 

     *      > i begins at one in the loop
    ***     > i = i + 2, n increments by 2
   *****    > i += 2
  *******   > i += 2
 *********  > i += 2
*********** > maximum length for diamond reached
 *********  > i = i - 2, n decrements by 2
  *******   > i -= 2
   *****    > i -= 2
    ***     > i -= 2
     *      > i reaches one, loop should end

Now we need to craft our loops to create this pattern. Let's go over the
basics of nested loops. If we had one loop printing out a line of stars,
it might look something like this:

var printStarLine = function(starNumber){
    var stars = '';
    for (var i = 0; i < starNumber; i++){
    stars += '*';
  }
    return stars;
}

Now if we called this function with an argument of 11, it would print:
'***********'. Great! Unfortunately, we need to print out a vertical line
of stars that will dictate the total like this:

*
*
*
*
*
*
*
*
*
*
*

The rule of nested loops is that if we have a loop inside of another loop, 
then the parent loop will no longer print across, as it needs to enter the
inner loop every time it runs. In this case, the parent loop will create
a vertical pattern. In our case, every time the loop adds a star, it also
needs to jump into our nested loop to do additional tasks.

Knowing this, it becomes obvious that we need to account for the spacing
between the stars, in order to form a diamond shaped pattern. Let's map out 
the potential spacing requirements in order to find some kind of pattern 
we can utilize to create our algorithm.

Since n is 11, we can assume that every vertical and horizontal space
will be filled with stars if no spacing restraints are put in place.

//if n is 11
//for (var i = 1; i <= n; i+= 2)
//  for (var j = 0; j < (n - i) / 2; j++)


//i begins at 1. We print one star. We move into the second for loop.
//This for loop will keep looping until its base condition is met, at
//which point we will go back up to the top loop.

//inside our second for loop, we add the spaces before our star.
//we use j  5 >> stars is i = 1
||||***    --> 4 >> i = i + 2.  
|||*****   --> 3
||*******  --> 2
|********* --> 1
***********
|********* --> 1
||*******  --> 2
|||*****   --> 3
||||***    --> 4
|||||*     --> 5

This pattern continues, as we fill in the leading spaces before the diamond.
|||||*||||| --> Now all that's left to do is fill in the 
||||***||||     with spaces that come after the stars. 
|||*****|||   
||*******||  
|*********| 
***********
|*********| 
||*******||  
|||*****|||   
||||***||||    
|||||*|||||