It's about to go down

Time to practice thinking and building like a true Software Engineer

OverView

  • Advanced Algorithmic Approach

  • Intermediate HOF #1

  • Building Your Tool Belt

  • Intermediate HOF #2

algorithmic approach

How to approach any software engineering problem

  • Data Modeling

  • Function Modeling

  • Pseudo Coding

  • Choosing your tools

 

OverView

Loop & Transform

loop = function(collection, callback){

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

};


transform = function(collection, callback){
	var results = [];
	loop(collection, function(element){
		results.push(callback(element));
	});
	return results;
};

In week 3 we focused on these two functions

Loop and transform allow us to write concise and elegant code.

var friends = ['Kmack', 'Jon', 'Albrey'];
loop(friends, function(friend){
    console.log(friend + ' is my friend :)');
};

// Kmack is my friend :)
// Jon is my friend :)
// Albrey is my friend :)


var enemies = transform(friends, function(friend){
    return {
     name: friend,
     evil: true,
    };
});

console.log(enemies)
// [{name: 'Kmack', evil: true}, {name: 'Jon', evil: true}..]

They are the tools and our toolbelts that get rid of clutter and confusion.

Loop & Transform

At this point, we know how to use these tools to build software

var friends = ['Kmack', 'Jon', 'Albrey'];
loop(friends, function(friend){
    console.log(friend + ' is my friend :)');
};

// Kmack is my friend :)
// Jon is my friend :)
// Albrey is my friend :)


var enemies = transform(friends, function(friend){
    return {
     name: friend,
     evil: true,
    };
});

console.log(enemies)
// [{name: 'Kmack', evil: true}, {name: 'Jon', evil: true}..]

A necessary skill is to figure out when it's best to use these tools.

Let's move away from sample problems and work on a real world example

Contract Work

Work Work Work Work Work

A client comes to us and says, "My store has been miscalculating transactions since opening back in February; each of our 19,284 transactions are not processed to include the .09% California state tax. I have a list containing the price of each transaction.

Can you build me software that will give me a list of each individual transaction calculated with the state tax."

The Problem

Break It down now

What they have: a list of prices.

What they need: a new list of prices + tax.

First we identify our inputs and outputs.

inputs: a list of prices.

outputs: a new list of prices + tax.

Break It down now

Model our input data.

inputs: a list of prices.







var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

Our users data is pretty straight forward

Most of the time it won't be this easy.

Break It down now

Mock test our function

var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

// input, array full of integers
var samplePricesWithTax = includetax(samplePrices); 
console.log(samplePricesWithTax);
// expected output tested by human test
// [31.61, 63.22, 18.53, 151.51, 101.37...]

inputs: a list of prices.

outputs: a new list of prices + tax.

Break It down now

Psuedocode it out





// go through a list of prices 
// calculate each  price plus the tax
    // gather the list of new prices
// return it to the user

Pseudocode should be a good mix of english and engineering language.

You can see it as a way to outline your function before building it.

Break It down now

Choose Your Tools







// go through a list of prices
    //calculate each price plus the tax
    // gather the list of new prices
// return it to the user

Let’s look at our tool belt and see what we should use for this:

Loop: Loops through a collection & performs some sort of action on each item, index, or the collection itself. 

Transform: Loops through a collection & performs some sort of transformative action on each element, and returns anarray containing each transformed element.: 

Break It down now

Let's Build It
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var includeTax = function(listOfPrices){
    // go through a list of prices
       //calculate each price plus the tax
       // gather the list of new prices
    // return it to the user
};

Add your pseudocode to the inside of your function

var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var includeTax = function(listOfPrices){
    // go through a list of prices
    return transform(listOfPrices, function(price){
        // calculate each price plus the tax
        // gather the list of new price
        return (price * 0.09) + price;
    });
    // return the new array to the user
    
};

Build our function according to our pseudocode

var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var includeTax = function(listOfPrices){
    // go through a list of prices
    return transform(listOfPrices, function(price){
        // calculate each price plus the tax
        // gather the list of new price
        return (price * 0.09) + price;
    });
    // return the new array to the user
    
};
var samplePricesWithTax = includeTax(samplePrices);
// [31.61, 63.22, 18.53, 151.51, 101.37, 14.17, 534.1, 10.9]

Test our function using our samplePrices

Takeaways

That was pretty straight forward right? 

Steps Taken

  1. Assessed the problem
  2. Figured out our inputs and outputs
  3. Modeled our Data
  4. Made a plan (pseudocode)
  5. Chose our tool (transform)
 

Great - Let's try another one!

Contract Work 2

Work Work Work Work Work

Our client comes back to us and asks us again whether we can build a piece of software that will add the tax to the prices. But this time, they only want to add the tax to prices over 50.

 

The Problem

Break It down now

What they have: a list of prices.

What they need: a new list of prices + tax.

 

First we identify our inputs an outputs.

inputs: a list of prices.

outputs: a new list of prices + tax.

CONDITION: THE NEW LIST ONLY CONTAINS PRICES OVER 50

Break It down now

Model our input data.

inputs: a list of prices.







var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

Our users data doesn't change.

Break It down now

Mock test our function

var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

// input, array full of integers
var samplePricesWithTax = overFiftyTax(samplePrices); 
console.log(samplePricesWithTax);
// expected output tested by human test
// [63.22, 151.51, 101.37, 534.1]

inputs: a list of prices.

outputs: a new list of over 50 prices + tax

Break It down now

Psuedocode it out





// go through a list of prices
    // check if price is over 50
        // calculate each price plus the tax
        // gather the list of new prices
// return it to the user

Break It down now

Choose Your Tools







// go through a list of prices
    // check if price is over 50
        // calculate each price plus the tax
        // gather the list of new prices
// return it to the user

Let’s look at our tool belt and see what we should use for this:

Loop: Loops through a collection & performs some sort of action on each item, index, or the collection itself. 

Transform: Loops through a collection & performs some sort of transformative action on each element, and returns anarray containing each transformed element.: 

Break It down now

Let's Build It
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    // go through a list of prices
        // check if price is over 50
            // calculate each price plus the tax
            // gather the list of new prices
    // return it to the user
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    // go through a list of prices
        transform(listOfPrices, function(price){
        // check if price is over 50
        
        });

            // calculate each price plus the tax
            // gather the list of new prices
    // return it to the user
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    // go through a list of prices
        transform(listOfPrices, function(price){
        // check if price is over 50
           if (price > 50){
            // calculate each price plus the tax  
            // add to the new list of new prices  
              return price + (price * 0.09);
       	   }
        });
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    // go through a list of prices
      return transform(listOfPrices, function(price){
        // check if price is over 50
           if (price > 50){
            // calculate each price plus the tax  
            // add to the new list of new prices  
              return price + (price * 0.09);
       	   }
        });
       // return new list of prices to user
};

Add your pseudocode to the inside of your function

Add our transform function

Sprinkle in a conditional

Make sure to return to our user

Test the end product

var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    return transform(listOfPrices, function(price){
        if (price > 50){
            return price + (price * 0.09);
	}
    });
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    return transform(listOfPrices, function(price){
        if (price > 50){
            return price + (price * 0.09);
	}
    });
};

var samplePricesWithTax = overFiftyTax(samplePrices);
console.log(samplePricesWithTax);
// [undefined, 63.22, undefined, 151.51, 101.37, undefined..];

Break It down now

overFiftyTax in depth
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    return transform(listOfPrices, function(price){
        if (price > 50){
            return price + (price * 0.09);
	}
    });
};

var samplePricesWithTax = overFiftyTax(samplePrices);
console.log(samplePricesWithTax);
// [undefined, 63.22, undefined, 151.51, 101.37, undefined..];
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    console.log("initializing transform function");
    return transform(listOfPrices, function(price){
      console.log(" current price is:", price);
      if (price > 50){
        console.log("price is over 50, returning new price");
        return price + (price * 0.09);
      }
        console.log("not going through if, still returning");
    });
};

var samplePricesWithTax = overFiftyTax(samplePrices);

How can we debug this?

Let's throw some console.logs in there

Break It down now

explanation

Transform does go through the collection and collect each element, but it can not choose which elements to collect.

Transform is not the right tool.

Let's try loop!

Break It down now

overFiftyTax with loop
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
// go through a list of prices
    // check if price is over 50
        // calculate each price plus the tax
        // gather the list of new prices
// return it to the user
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
// go through a list of prices
    loop(listOfPrices, function(price){
     // check if price is over 50
      // calculate each price plus the tax
      // gather the list of new prices
     // return it to the user
    });
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
// go through a list of prices
    loop(listOfPrices, function(price){
     if (price > 50) {
      // calculate each price plus the tax
      // gather the list of new prices
     // return it to the user
     }
    });
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
// go through a list of prices
    loop(listOfPrices, function(price){
     if (price > 50) {
      // calculate each price plus the tax
      var newPrice = price + (price * 0.09)
      // gather the list of new prices
     // return it to the user
     }
    });
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    var result = [];
// go through a list of prices
    loop(listOfPrices, function(price){
     if (price > 50) {
      // calculate each price plus the tax
      var newPrice = price + (price * 0.09)
      // gather the list of new prices
      result.push(newPrice)
     // return it to the user
     }
    });
};
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    var result = [];
// go through a list of prices
    loop(listOfPrices, function(price){
     if (price > 50) {
      // calculate each price plus the tax
      var newPrice = price + (price * 0.09)
      // gather the list of new prices
      result.push(newPrice)
     }
    });
    // return it to the user
    return result;
};

Let's test it

Break It down now

testing overFiftyTax with loop
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    var result = [];
    loop(listOfPrices, function(price){
     if (price > 50) {
      var newPrice = price + (price * 0.09)
      result.push(newPrice)
     }
    });
    return result;
};
var samplePricesWithTax = overFiftyTax(samplePrices); 
console.log(samplePricesWithTax);
// [63.22, 151.51, 101.37, 534.1]
var samplePrices = [29, 58, 17, 139, 93, 13, 490, 10];

var overFiftyTax = function(listOfPrices){
    var result = [];
    loop(listOfPrices, function(price){
     if (price > 50) {
      var newPrice = price + (price * 0.09)
      result.push(newPrice)
     }
    });
    return result;
};
var samplePricesWithTax = overFiftyTax(samplePrices); 
console.log(samplePricesWithTax);

Takeaways

Steps Taken

  1. Assessed the problem
  2. Figured out our inputs and outputs
  3. Modeled our Data
  4. Made a plan (pseudocode)
  5. Chose our tool (transform)
  6. Chose the wrong tool
  7. Went back and built something new for our specific need
 

Sometimes it's going to be difficult to figure out which tool you need from the onset.

It is important to keep in mind the exact purpose of your function  before choosing to build with it.

Exercises

https://github.com/TelegraphPrep/CarFaxDotCom

Understanding

Distill

Overview:

  • What distill does                            
  • Build distill
  • Learn how to use distill

Functions We Covered:

  • loop
    • can be used to iterate through collections (side effect)                           
  • transform
    • used to change values in a collection and produce a new array (returning a value)
  • filterBy
    •  predicate determines if the elements within the collection will changed and/or be return in a new array

What the __ is distill?

var numbers = [59, 72, 21, 16]

    var sumOfNumber = distill(numbers, function(sum, currentNumber){
        return sum + currentNumber;
    }, 0);

    console.log(sumOfNumbers) // 168

** Notice that the value is not returned in an array...

Lets Build distill

//distill takes a collection, a callback, and a startValue.

 

//iterates through the collection and on each iteration updates the startValue to 
//whatever the callback evaluates to.



// After iterating through the collection it returns the updated startValue to the user.

Lets write in plain english the functionality of distill

Lets Build distill

// distill takes a collection, a callback, and a startValue.

var distill = function(collection, callback, startValue){
        startValue = startValue || 0;

//iterates through the collection and on each iteration updates the startValue to 
    //whatever the callback evaluates to.

        loop(collection, function(element){

            startValue = callback(startValue, element, index);
        });
// After iterating through the collection it returns the updated startValue to the user.
    return startValue;

   }


 

Lets write in plain english the functionality of distill

Drop down and Get your distill on..

 var numbers = [1, 2, 3];

 distill(numbers, function(previousValue, currentValue, index){

   console.log(previousValue, currentValue, index);
   return previousValue + currentValue;

});


// This is logged to our console:                    


    // 0  1  0                   previousValue: 0  currentValue: 1  index: 0
                                  
    // 1  2  1                   previousValue: 1  currentValue: 2  index: 1
    
    // 3  3  2                   previousValue: 3  currentValue: 3  index: 2

    // 6                         previousValue: 6 



 

Lets practice using distill and dig deeper into distillation

Drop down and Get your distill on..

 var numbers = [1, 2, 3];

 distill(numbers, function(previousValue, currentValue, index){
   console.log(previousValue, currentValue, index);
   return previousValue + currentValue;
}, 100);


// This is logged to our console:                    


    // 100  1  0                    previousValue: 100  currentValue: 1  index: 0
                                  
    // 101  2  1                    previousValue: 101  currentValue: 2  index: 1
    
    // 103  3  2                    previousValue: 103  currentValue: 3  index: 2

    // 106                          previousValue: 106



 

Lets practice using distill and dig deeper into distillation

 Contract Work

Another day, another dollar...

Sony contacted us about a project.  They would like you to parse through iTunes sales for the top 5 albums of March and get the total albums sales on iTunes from those top 5 albums.

Modeling Our Data

Input:  Array

 

Output: Interger

Lets get this Check!

// Their data is stored in an object like this:

var topFiveAlbums = [
    {
        title: "Purple Rain",
        author: "Prince",
        sales: 1000000
    },
    {
        title: "Life of Pablo",
        author: "Kanye West",
        sales: 250000
    },
    {
        title: "Reflektor",
        author: "Arcade Fire",
        sales: 150000
    },

    {
        title: "25",
        author: "Adele",
        sales: 1000000

    },

    {
        title: "Anti",
        author: "Bad Gal RiRi",
        sales: 500000

    }
];

Lets get this Check!

// Get an array of sales values only
var arrayOfSales = transForm(topFiveAlbums, function(albums) {
    return albums.sales;
});

console.log(arrayOfSales) // [10000, 250000, 150000, 1000000, 500000];




// Condense the array's values from left to right
var totalSales = distill(arraysOfSales, function(prev, curr) {
    return prev + curr;
});


console.log(totalSales) // 1,901,000


//    prev: 0             curr: 10000

//    prev: 10000         curr: 250000

//    prev: 251000        curr: 150000

//    prev: 401000        curr: 1000000

//    prev: 1410000       curr: 500000

//    prev: 1,901,000

The Real Distill.

var distill = function(collection, callback, startValue){
        startValue = startValue || 0;
        loop(collection, function(element){

            startValue = callback(startValue, element, index);
        });
    return startValue;

   };

Review our current version of distill:

The Real Distill.

// distill takes a collection, a callback, and a startValue.
    //if the start value is not given
        //if the collection is an array,
            // remove the first value in the array and use that first value
                // in the array as the startValue
  //iterates through the collection and on each iteration updates the startValue 
        // to whatever the callback evaluates to.
   // After iterating through the collection it returns the updated startValue to the user.

The Real Distill.

// distill takes a collection, a callback, and a startValue

var distill = function(collection, callback, startValue){

        //if the start value is not given
            //if the collection is an array,
            // remove the first value in the array and use that first value
                // in the array as the startValue

        startValue = startValue || null
        if(startValue === null){
            if(Array.isArray(collection)){
                startValue = collection.shift();
            }

        }

        //iterates through the collection and on each iteration updates the startValue 
            // to whatever the callback evaluates to.

        loop(collection, function(element, index){
            startValue = callback(startValue, element, index);
        })

     // After iterating through the collection it returns the updated startValue to the user.

     return startValue;
};

The Real Distill.

var numbers = [1, 2, 3];

distill(numbers, function(prev, curr, index){

    console.log(prev, curr,  index);
    return prev + curr;

});



  // This logs:


    // 1  2  0
    // 3  3  1
    // 6



// As you can see, the callback actually didn't iterate over the first element of the array. 
// Instead, prev was set to the value of the first element. It has to work that way because 
// otherwise distill wouldn't have a starting value for prev.

// The function ran three times, but on the last call, it wasn't given a current 
// element since there were no elements left in the array.

The Real Distill.

// Here is another example:

var numbers = [1, 2, 3];

distill(collection, function(prev, curr, index) {

    console.log(prev, curr, index);

    return prev + curr;

}, 100);







// Outputs:

// 100  1  0
// 101  2  1
// 103  3  2
// 106


// In addition to the callback function, we also passed in an starting value for prev. 
// You see that the callback did iterate over the first element in the array,
// since it had an initial value to work with.

The Real Distill.

// distill only good for working with integers? Whatttt? Nah. Check this out:

var relationashipArray = [

    ["Kmack", "Jon"],
    ["Jon", "Albrey"],
    ["Albrey", "Bianca"]
];

var relationshipMap = distill(relationshipArray, function(prev, curr) {

    prev[curr[0]] = curr[1];

    return prev;

}, {});


console.log(relationshipMap);

// Outputs: 

//  {
//    "Kmack": "Jon",
//    "Jon": "Albrey",
//    "Albrey": "Bianca"
// }


// We used distill to transform our relationship array from an array of arrays into 
// an object where each key value pair describes the relationship.

Time to practice

https://github.com/TelegraphPrep/BookstoreApplication

It's About To Go Down

By telegraphprep

It's About To Go Down

Upping the Ante at Telegraph Prep+

  • 1,360