Categories
Coding

What Are The JavaScript Equivalents Of “AND” And “OR”?

In Javascript we use the && (double ampersand) and || (double pipes) to denote and and or respectively. Think of it is a symbolic representation of the English words.

However, we can use both of these symbols to determine if something is truthy. This can also help with variable assignment if we’re relying upon other variables having values.

Let’s see if you can follow the logic with these examples.

If you are testing whether a variable is truthy and want to return another truthy value you can do the following:

var e = “test”;
var f = 2;
console.log( e && f ); // as both variables are true returns the last variable `f` being 2.

If we changed the value of e to a falsey value such as false, null, or 0, we get…

var e = null;
var f = 2;
console.log( e && f ); // => null

If we switch it, such that f is a falsey value we get…

var e = 2;
var f = 0;
console.log( e && f ); // => 0

So in both of the previous two cases the falsey value gets returned.

What happens then if we replace the && with ||, here are our results:

var e = "test";
var f = 2;
console.log( e || f ); // => "test"

Notice how we get the first truthy value.

var e = null;
var f = 2;
console.log( e || f ); // => 2

And again we get the first truthy value being the variable f.

So what would you expect if we now started combining these expressions?

var e = null;
var f = 2;
console.log( e && f || 1 ); => 1

Why?

As the ( e && f ) expression returns the first falsey value, being null it’s then used in the second comparative statement null || 1 and we know that with || comparisons it returns the first truthy value being 1 (as null is falsey).

Cool.

Categories
Coding

JavaScript Array Methods

When starting to learn JavaScript there are a few handy built-in functions when iterating through arrays. Each have their distinct flavour and it depends on what you’re trying to achieve from each.

Let’s explore each function and the benefit it provides:

Map

The map method on the Array prototype enables the user to create a new array with newly inserted or modified values.

var oldArray = [ { name : “Ryan”, age: 31 }, { name: “Sara”, age: 21 } ];

var newArray = oldArray.map( function( el, i, arr ) {
    newObj = el;
    newObj.isOld = false;
    if ( el.age > 30 ) newObj.isOld = true;
    return newObj;
});

console.log( newArray ); // => [ { name: “Ryan”, age: 31, isOld: true }, { name: “Sara”, age: 21, isOld: false } ]

Another example provided on MDN is the square root of numbers:

var numArray = [1, 3, 6, 9];

var results = numArray.map( Math.sqrt );

console.log( results ); // => [ 1, 1.735..., 2.4494..., 3 ]

Cool.

Certainly will come in handy when using this with Google App Script.

Filter

The filter method on the Array prototype enables us to receive a new array according to the parameters entered into the function.

var oldArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];

var newArray = oldArray.filter( function( el, i, arr ) { 
    return ( el % 2 === 0 );
} );

console.log( newArray ); // => [2, 4, 6, 8]

Learning Javascript is such fun!

Especially when you work with data on Google Spreadsheets every day!

Some

The some method on the Array prototype returns a boolean value if an element in the passed array meets the condition of the function. Once the function fires true the function returns and no further processing is done.

Here’s a quick example:

var numArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var isDivisibleBy10 = numArray.filter( function( el, i, arr ) {
    return ( el % 2 === 0 );
} ).some( function( el, i, arr ) {
    console.log( el ); // => 2, 4, 6, 8
    return ( el % 10 === 0 );
} );
console.log( isDivisibleBy10 ); // => false

As from above we can see that the some function AFTER the filter function has filtered out all even numbers from the array returns false because the condition within the some method never hit true.

Let’s test another some function using a different example:

var numArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

var isDivisibleBy2 = numArray.filter( function( el, i, arr ) {
    return ( el % 2 === 0 );
} ).some( function( el, i, arr ) {
    console.log( el ); // => 2
    return ( el % 2 === 0 );
} );
console.log( isDivisibleBy10 ); // => true

Note here that the console.log within the some function only iterated to the first element in the new filtered array because once the condition was met there was no need to continue looping through the remainder of the filtered array.

Sort

The sort function requires a comparator as it’s parameter. This is the following format of the function:

Array.prototype.sort( compareFunction( a, b ) {
    //...
} ); 

From MDN:

  • If compareFunction( a, b ) returns less than 0, sort a to a lower index than b, i.e. a comes first.
  • If compareFunction( a, b ) returns 0, leave a and b unchanged with respect to each other.
  • If compareFunction( a, b ) returns greater than 0, sort b to a lower index than a, i.e. b comes first.

Therefore, with the following array of elements where you want to sort by id then by rank we would use the following:

var arr = [ { id : 1, rank : 3 }, { id : 1, rank : 1 }, { id : 5, rank : 5 }, { id : 3, rank : 2 }, { id : 3, rank : 1 } ];

var r = arr.sort( function( a, b ) {
    // prioritise the elements up top first
    if ( a.id > b.id ) return 1;             // ascending order by id
    if ( a.id < b.id ) return -1;
    // if the id values are the same then let's sort by rank
    if ( a.rank > b.rank ) return -1;    // descending order by rank
    if ( a.rank < b.rank ) return 1;
});

console.log( r ); // => [ { id : 1, rank : 3 }, { id : 1, rank : 1 }, { id : 3, rank : 2 }, { id : 3, rank : 1 }, { id : 5, rank : 5 } ];

Easy!

After reading through some of the interesting articles in this week’s Javscript Weekly (which I highly recommend) I asked myself the question:

Just what happens in Javascript’s Array.prototype.sort() method?

So I decided to mock up a quick test case to actually try and see what was happening, here is the simple test case:

var arr = [ 5, 10, 3, 8 ];

function sorty( a, b ) {
    console.log( a + " v " + b );
    if ( a > b ) return 1;
    if ( a < b ) return -1;
    return 0;
}

console.log( arr.sort( sorty ) );

Here is what the results spat out:

5 v 10
10 v 3
5 v 3
10 v 8
5 v 8
[ 3, 5, 8, 10 ]

Notice the sequence of events with how the sort function progressed through the elements in the arr array:

  1. Compare arr[0] = 5 and arr[1] = 10 => returns -1
  2. We have a new array, let’s call it newArray = [ 5, 10 ]
  3. Compare last element of newArray[1] = 10 to arr[2] = 3 => returns 1
  4. Compare newArray[0] = 5 element to arr[2] = 3 => returns 1
  5. Insert new element at start of newArray = [ 3, 5, 10 ]
  6. Compare newArray[2] = 10 element to arr[3] = 8 => returns 1
  7. Compare newArray[1] = 5 element to arr[3] = 8 => returns -1
  8. Insert this element between 2nd and 1st element in newArray = [ 3, 4, 5, 10 ]
  9. newArray is returned.

By outputting the results like this we can see how the sort function works behind the scenes. And we can clearly see that with each new element in the initial array it loops through the newly created sorted array until it finds a difference from what is returned when comparing two adjacent elements in the new array and then inserts that element between those elements.

This exercise proved quite insightful, hopefully it does for you too!

Reduce

For any array where you are using the filter method with the map method chained afterwards, you could simply transform both of these calls down to one reduce method, as per the following example:

var a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
var b = a.filter( function( el ) {
    return el % 2 === 0;
}).map( function( el ) {
    return el * 5;
});
console.log( b ); // => [ 10, 20, 30, 40 ] 

var c = a.reduce( function( result, el ) {
    if ( el % 2 === 0 ) result.push( el * 5 );
    return result;
}, [] ); 
console.log( c ); // => [ 10, 20, 30, 40 ]

As you can see the reduce method is a lot simpler and easier to read.

I’m enjoying using the reduce array function a lot more in my programming with Google Spreadsheets.

I find that I can easily get what I want when I grab using the var data = sht.getDataRange().getValues() methods.

However, one aspect I stumbled on today had me a little stumped was the following (see if you can spot WHY it didn’t work):

var arr = [ 1, 2, 3, 4, 5 ];

var answer = arr.reduce( function( result, el, i ) {
  if ( el % 2 === 0 ) result.total += el;
  return result;
}, {} );

console.log( answer ); // => { total: NaN }

Why did the total property return NaN (not a number)?

Simply because the property was never initialised to begin with! It would be no different to the following code:

var test = {};
test.inc = undefined;
test.inc += 1;
console.log( test ); // => { inc : NaN }

While the variable had been initialised as an Object the property itself had not and therefore was undefined when it came to increment by 1.

Therefore, producing NaN.

To resolve this issue when using the reduce array method, simply initialise the object’s properties, like so:

var arr = [ 1, 2, 3, 4, 5 ];

var answer = arr.reduce( function( result, el, i ) {
  if ( el % 2 === 0 ) result.total += el;
  return result;
}, { total : 10 } );

console.log( answer ); // => { total: 16 }

By setting the property we are incrementing over to 10, now when the property is called it will apply adding 2 and then 4, resulting in a value of 16.

Why will the following Array.reduce() method not work?

var x = [ 1, 2, 3 ];
var y = x.reduce( function( prev, el, i, self ) {
    if ( el === 2 ) return { works : el };
}, {} );
console.log( y ); // => undefined

The purpose of the above reduce function is to just transform the array into an object and return the element to a property key. In other words the expectation was for the function to return { works: 2 }, but instead I get undefined.

Why?

As the reduce method loops through each element in the arr array, if the element does NOT satisfy the condition it returns undefined. As the LAST element in this array did NOT satisfy the condition it returns undefined again.

Therefore, when iterating through the reduce method you will want to return the previousValue (or in our example above the first parameter prev).

var x = [ 1, 2, 3 ];
var y = x.reduce( function( prev, el, i, self ) {
    if ( el === 2 ) prev.works = el;
    return prev;
}, {} );
console.log( y ); // => { works: 2 }

Remember, you’re always returning the prev variable and any conditionals need to be assigned to that variable.