Let’s Talk Template Literals

It’s interesting that there are so many ways to STDOUT text to the screen. Let’s look at a few of them in JavaScript (ES6) and Python (3.6)

Concatenation: This works in both JavaScript (console.log) and Python (print). “The first half of the sentence ” + “is joined to the second with a plus sign between the halves.” Also works with variables. “Hello, ” + user.name + ” and welcome to our shopping site.” Do pay attention to where spaces are.

Embedded expressions: Javascript allows developer to include simple expressions as well.

console.log( "Hello, " + user.name + ". Your total is: " + (purchase.subTotal + purchase.tax + purchase.delivery) + ".")

Hello, Kristopher. Your total is $123.45.

String formatting: Python 3.6 allows developers to include variables mid-string as follows:

print('We are the {} who say "{}!"'.format('knights', 'Ni')) 

We are the knights who say "Ni!"

But if you need to refer to the position of the argument (values passed in to ‘format()’ there’s also:

print('{0} and {1}'.format('spam', 'eggs')) 
spam and eggs

or:

print('{1} and {0}'.format('spam', 'eggs')) 
eggs and spam

As well as keyword arguments, though I find this exceptionally cumbersome and wonder why the developer wouldn’t jut hard-code the values into this sentence. I’m including it because it’s in the Python docs and isn’t noted as being too archaic:

print('This {food} is {adjective}.'.format(food='spam', adjective='absolutely horrible')) 

This spam is absolutely horrible.

My personal preference, added to Python in 3.6 is the f-string

print(f'Welcome, {user.name}! Today's special is {special.name} and is on sale for {special.price}.')

Welcome, Kristopher! Today's special is Singing Rooster Coffee 12oz vacuum bag and is on sale for $10.

This is really easy to debug, in part because it reads very much like the end sentence, without extra punctuation. I also don’t have to type-cast my variables like in Python 2.7 (which required %s, %f and %i when referring to strings, floats and integers). Take a look at the Python docs for more examples and explanations: https://docs.python.org/3/tutorial/inputoutput.html

In JavaScript I’m growing attached to template literals. Like the f-string a template literal reads very much like the final product.

console.log(`Welcome, ${user.name}! Today's special is ${special.name} and is on sale for ${special.price}.`

Welcome, Kristopher! Today's special is tomato soup with grilled cheese sandwich and is on sale for $6.75.

The only catch here is to look for backticks (“ the keys that are left of the “1” on a US keyboard). At first they can look like single quotes, though most IDEs I’ve worked with do a good job of making the angle very obvious. MDN has done a great job with the documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

Advertisements
Let’s Talk Template Literals

Variables inside JavaScript Functions

“It doesn’t matter where I declare my variables, right? They just get hoisted….. right?”
~ what this developer had to be thinking right before they committed this code.
Not so fast. Let’s just do a simple test using the developer tools to see whether JavaScript hoists inside functions.

function testy(){
  if(testy===true){
    console.log("It's true! I'm testy!")
  } else { 
    console.log("I'm not testy today")
  }
  var testy = true
}

Before I go showing the answer, what do you think the console shows?

.

.

.

.

.

.

.

.

Screen Shot 2018-09-18 at 9.09.42 PM

 

So it looks like JavaScript does not hoist variable declarations inside of functions. Let’s double check that with a quick change.

function testy(){
  var testy = true
  if(testy===true){
    console.log("It's true! I'm testy!")
  } else {
    console.log("I'm not testy today")
  }
}

 

What happens this time? I won’t keep you in suspense like last time:

Screen Shot 2018-09-18 at 9.12.10 PM

 

And there you have it.

Variables inside JavaScript Functions

Notes for the Future: JavaScript Array Methods

This is mostly for me, but you may find it helpful, too. I periodically need a reminder of my JavaScript array methods, and want them in a handy place where I’ll find them.

Make an array:
var constructorArray = new Array();
var regularArray = [];

Test for Array-ness:
console.log(Array.isArray(someArray));

Use these all the time:
myArray.length;
myArray[x]; //where x is the xth position in the array. JavaScript array indices start at zero.
myArray[y] = “thing”; //adds “thing” to myArray at the yth index. If y is not contiguous with the current indexing, “thing” will be added at y and all the unfilled spaces between y and x will be filled with ‘undefined’ values.
delete myArray[x]; //replaces the value at the xth index with “undefined”

For all those ‘do this thing to a string’ whiteboard problems:

myArray.toString();

Will comma separate the items in an array

myArray.join();

By default each item in the string being joined will be separated with a comma. myArray.join(separator=”) will join the items with no characters between them.

Unshift/Push/Shift/Pop:

arrayMethods
Image produced by author.

[Update August 16, 2018:
NB: Array.shift() removes the 0th index and returns it. This mutates the original array and the returned value is whatever myArray[0] was when .shift() was applied. If you are trying to recursively traverse the array you will need to use Array.slice(1) so the function works on the copied array:

EXAMPLE:

This is my solution to a CodeWars problem that is set up thusly:

Write a function called max that takes one argument, an array, and returns the maximum value of that array.
Rules:
You cannot use Math.max (duh!)
You can only use const to declare any variables
You cannot use any loops like for or while
You cannot use any other argument than the one passed to the function
If the array is empty then return -Infinity, just like with Math.max.apply(null, [])
You cannot use any Array.prototype methods like forEach, map, filter, or reduce
function max(arr){
  if(arr.length ===0){
    return-Infinity;
  } elseif(arr.length ===1){
    return arr[0];
  } else{
    if(arr[0]< arr[1]){
      return max(arr.splice(1));
    } elseif(arr[0]> arr[1]){
      return max((arr.splice(1)).concat(arr[0]));
    }
  }
}
max([1,2,3,4,5])  // returns 5
function max(arr){
  if(arr.length ===0){
    return-Infinity;
  }elseif(arr.length ===1){
    return arr[0];
  }else{
    if(arr[0]< arr[1]){
    return max(arr.shift());
    } elseif(arr[0]> arr[1]){
      return max((arr.shift()).concat(arr[0]));
    }
  }
}
max([1,2,3,4,5])  // returns undefined because the shifted value (1, a number type) is being passed into max, which is expecting to work on an array.
END UPDATE ]

Splices:

myArray.splice(2,1,"thing");

at index 2 removes 1 item, inserts “thing” at that index. (Though this is a valid use, myArray[2] = “thing” is probably more performant for the same result in JavaScript).

myArray.splice(2,0,"thing");

At index 2 removes 0 items adds “thing”. If there is already something at index 2, that value’s index is incremented by one and “thing” becomes the value at index 2.

[ UPDATE! Feb 5, 2018:
At work I need to remove an item from an array’s sub-array but there is no guarantee that it will always be loaded at index 2 in the sub-array. Here’s how to remove the known thing regardless of where it lives in the sub-array:

// yields an index number
var removeItemIndex = myArray[‘subArrayName’].indexOf(‘thingToRemove’); 
// use this value as the index to be removed
myArray[‘subArrayName’].splice(removeItemIndex, 1);

END UPDATE ]

REVERSE AN ARRAY:

var myArray = ["Z", "Y", "X", "W"];
myArray.reverse();

Yields [“W”, “X”, “Y”, “Z”].  Use this with .join() and .toString() to reverse those immutable JS strings. This does not leave the original array.

* non-destructive array reversal:

function reverse(array) {
  var tempArray = [];
  var len = array.length; // this is the length of the array being passed in
for (var i = (len -1); i  !== -1; i--) { //start at the 'left' end of the array, work back to the 0-th position and include 0-th index. Checking for i !== 0 will not include the 0-th index. i is negatively iterated with minus minus, in case the rendered font doesn't show that.
tempArray.push(array[i]);
    }
    return tempArray;
};
reverse(myArray);

Don’t forget to call your functions

.SORT():

  • Alphabetic information:
    var myArray = ["Z", "Y", "X", "W"];
    myArray = myArray.sort();

    .sort() is a lexicographic method, which means the method wants to put these items in alphabetic order based on their Unicode code points. .sort() leaves the array in-place for the sort, so no additional arrays are created.

  • Numeric information:
    var myArray = [0, 10, 4, 12, 2, 1, 9];
    function compare(a,b){
    return (a-b);
    }
    myArray = myArray.sort(compare);
    console.log(myArray); // [0,1,2,4,9, 10,12]

    Without doing a compare, .sort puts 10 after 1 because of their Unicode code values.

.concat()  to combine arrays:

myArray = ["A", "B", "C"];
 myOtherArray = [1, 2, 3];
myNewArray = myArray.concat(myOtherArray);
console.log(myNewArray); // ["A", "B", "C", 1, 2, 3]

Slice:
(Do not confuse with splice)
.slice() takes two arguments, which index to start at and which index to stop in front of. .slice() will create a copy of the original array, return the values that were sliced and leaves the original array unchanged. If you only want the slice then use the same array name as the array being sliced.

var myArray = ["A", "B", "C", 1, 2, 3];
myExample = myArray.slice(1,4);
console.log(myExample); // returns ["B", "C", 1]
console.log(myArray); //returns ["A", "B", "C", 1, 2, 3]
myArray = myArray.slice(1,4);
console.log(myArray); // returns ["B", "C", 1]

Slice is also useful as a deep copy of an array in ES5:

var clone = myArray.slice(0)

whereas in ES6 we can do

let clone = [...myArray]

.every()
.every() tests every item in an array for a given criteria. .every() takes a callback and arguments (the array(s) in question). From the MDN docs:

function isBigEnough(element, index, array) {
  return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough);   // false
[12, 54, 18, 130, 44].every(isBigEnough); // true

ES6 gives us .find()

.find() returns the first value that meets the criteria in the function. Example from MDN

var array1 = [5, 12, 8, 130, 44];

var found = array1.find(function(element) {
return element > 10;
});

console.log(found);
// expected output: 12

This is probably not the best way to find multiple items. For a situation like that I would use…

.filter() (ES5 method)

Per MDN: The filter() method creates a new array with all elements that pass the test implemented by the provided function. The original array is left untouched.

let array1 = [5, 12, 8, 130, 44];

const filtered = array1.filter(value => value > 10)

console.log(filtered);
// expected output: [12, 130, 144]

.map() (ES5 method)

The map() method creates a new array with the results of calling a provided function on every element in the calling array.

var array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

.reduce() (ES5 method)

The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

 

 

Notes for the Future: JavaScript Array Methods

Notes for the Future, Part 3 – Palindrome Finder (Updated)

[Edit Aug 27, 2018: I decided I would mess around with how many ways I can find palindromes and wrote this repl.it https://repl.it/@kmskelton/play-with-palindromes The code below can stand to have some array methods applied to it, but I’m keeping it for posterity. ]

[Original: May 15, 2017] I’ve heard from several sources that finding palindromes is popular during interviews. I had this challenge as part of the final assessment for my JavaScript course and this is a slightly modified version of what I came up with. This will find the longest palindrome in a string. If there are two equal length palindromes in the string (e.g. “racecar tacocat”) it will return the first. I’ve included notes as I went along.

function paliFinder(inputString) {

  var result = '';

  if (inputString === undefined || inputString.length === 1) {

    return console.log ("result = 'No valid string submitted!'");

  } // handle errors if user tries one letter or simply nothing

  var inputString = inputString.replace(/[^\W_\s]/gi, ''); //remove spaces and punctuation

  var paliArray = inputString.toLowerCase().split(''); //split the modified string on each character and store that as an array

  for (var i = 0; i < paliArray.length; i++) { //loop through once

    var paliMaybe = [];

    var paliMaybeString = '';  // if you're copy/pasting this for your job interview

    var checkArray = []; // I'm gonna make you work for it

    var checkString = ''; // because that's just how I am

    for (var j = i; j < paliArray.length; j++) { // loop through again

      if (paliArray[j] === ' ') {

        break 

      };

      checkArray.push(paliArray[j]); // each letter is added to the end of this array

      checkString = checkArray.join('')

      .toString(); //make the array a string

      paliMaybe.unshift(paliArray[j]); // each letter is added to the front of this array

      paliMaybeString = paliMaybe.join('')

      .toString(); //make the array a string

      if (checkString.length > 1 &&  // don't forget to delete this comment, too

        checkString === paliMaybeString &&

        checkString.length > result.length) {

        result = checkString;

      }

    } 

  }

return console.log(result);

}

paliFinder("tacocat in a racecar")

// tacocat

This is not quite bulletproof, but the only example I’ve found that will break it is something like “A A” with a space between the letters. For some reason it just decides to return nothing.
It’s also not particularly fast with two loops, a push and an unshift. It’s somewhere in the neighborhood of 2n^2 or something crazy.

Notes for the Future, Part 3 – Palindrome Finder (Updated)