Sorting numbers within a JavaScript array

The problem

You need to sort this JavaScript array in numeric order:


var numbers = [2, 1, 11];

Arrays have a sort method, so lets try using that


var numbers = [2, 1, 11];

console.log(numbers.sort());

The output from running this in Chrome 67 is that the array is now sorted as:

[1, 11, 2]

Which is not what we want, the number 11 is in the wrong place.

The Reason

This result is produced because using the JavaScript sort() without a compare method array causes elements to be sorted by converting them to strings and comparing strings in Unicode code point order.

Apologies! That was a bit opaque so lets take that last paragraph apart. The sort method first converts the numbers to strings so we conceptually have

“2”, “1”, “11”

The  UTF-16 code for each of these are obtained and these are respectively

0032, 0031, 0031 0031

With both “1” and “11”  having a lower UTF-16 code than “2” it should now be slightly clearer why 11 appears before 2.

The Solution

The sort method compares two values to determine which should come first. These two values are usually referred to as a and b. The sort method can have an function, anonymous or named as a parameter. This function is a referred to as a compare function. The compare function allows you as the developer to define the rules for sorting.

The compare function should return a number. That number will be  used to determine which of a or b comes first.

<0

If the compare function returns less than zero a should be shown before b

0

If the compare function returns zero, the a and b should remain in the same order

>0

If the compare function returns greater than zero b should be shown before a

Shown below is an example of anonymous compare function:

function(a, b) {  

  return a - b; 

}

This function can then be passed to the sort() method as shown below. The calls to console.log are instrumentation that you can use to see what is going during each of the three times the compare function is invoked.

 

  var numbers = [2, 1, 11];
  console.log('Original order: ' + numbers);

  numbers.sort(function(a, b) {
   console.log(a + ' - ' + b + ' = ' + (a - b));
   return a - b;
  });   

  console.log('Expected order: ' + numbers);

Pasting this into the Chrome console window will produce the following output:

20180724_02 .JPG

Stepping through the output, first displayed is the array in it’s original order.

The next two lines shows the results of the compare function and in this invocation the parameters a and b have the values 2 and 1 respectively

2 – 1 = 1 means that the compare function returns a number greater than 0 so that 1(b) will be shown before 2 (a)

The next line shows that the and b values for the final invocation are now 2 and 11.      2 – 11 = -9 which means that the compare function this time return a number less than zero so that 2(a) will be displayed before 11(b)

The final line shows the results of the sort and now the numbers are sorted as expected.

Acknowledgements

Another plug for this wonderful book which was the inspiration for this page Javascript and JQuery book by Jon Duckett

 

What I learnt from building ugly ToDo lists in JavaScript and JQuery

20180712_1.JPG
Not pretty

Here’s what I learnt when building two To Do applications. One was built using pure JavaScript and the other used jQuery with a smidgen of JavaScript.

Each To Do list had to satisfy several basic functions. The user had to be able to add tasks, remove tasks, save tasks and be able to retrieve them. These To Do lists are far from production quality but what I have learnt by building them will help immeasurably in my next project and the one after that and so on.

Tools

Both examples were built using Visual Studio Code, jQuery 3.3.1 and Chrome 67. Any text editor can be used instead of Visual Studio Code but I have found it to be a joy to use and is now a firm favourite of mine.

Javascript

Practical experience of using Web Storage to save and retrieve tasks.

 

Understanding Immediately Invoked Function Expression or IIFE. Whilst there are other reasons to use an IFFE such stopping name collisions in this example I have used an IFFE to call a function that retrieves the saved tasks once the Document Object Model (DOM) has been loaded.

 

Although there is only 200 lines of JavaScript I have become familiar and thankful for Chrome Devtools. Pressing F12 has become second nature when I need to find out what is actually going on with my code. From seeing errors shown in the console to adding breakpoints via sources, I have found Chome Devtools so intuitive to use.

 

Creating and removing input items dynamically. The To Do list needed functionality whereby a user could add and remove tasks which translated to being able to create input elements and attach them to the parent. When removing an item, the code needed to find out which task had been selected for removal before removing it.

 

When refreshing my knowledge of JavaScript I was having trouble getting to grips with which selector I should use when selecting elements of the DOM. Experimenting with different JavaScript selectors such as querySelector, getElementById for single element node selection and getElementsByName for selecting more than one node gave me a greater understanding of working with the DOM and the difference between the code required to handle one node compared to when a node list is returned.

 

jQuery

Use of the jQuery ready method. All the code used by index.js is contained within the jQuery’s ready method, the shorthand version of which is shown below
$(function() { 

   all code goes between the opening and closing brackets

}
Doing this ensures that the DOM has tree has been constructed by the browser.

 

Similar to the JavaScript version I learnt how to create and remove items dynamically and attaching or detaching them from the parent as necessary.

 

When working with items using the id attribute requires use of the # symbol followed by the unique name.  e.g. to select the following element:
0 tasks
The following jQuery expression is used
$('#Count').text($countOfItems);
Refactoring. As I was building this second ToDo list I could see ways to improve and do things better with less code. In addition whilst working on this version I discovered a bug with that would have also affected the JavaScript version as well so I was able to go back and fix it in both.

 

I really enjoyed working with jQuery and love the simplicity of selecting items and then chaining of actions to do interesting work with the selection but there were times that I thought pure JavaScript was a better fit. Within index.js you can see the function getLocalStorageAsArray() does not use jQuery.
Use of .each(). jQuery allows you to update all of the elements selected without the need for a loop. However there were times when I needed to perform some actions on each element found by a selection which meant use of the .each() method which allows you to recreate a loop in scenarios when it is required. This required a slight shift in thinking because it is too easy to think a loop is required (coming from another language) when a jQuery selection is all that is really needed.

 

A pleasant side effect of  working with .each() was that I needed to find out which iterator my .each() was currently processing and during my hunt for an answered discovered that the jQuery official documentation is really good and it succinctly pointed me to using using the index argument.

 

The number of lines of code when using jQuery versus pure JavaScript reduced the lines of code by about 50 lines (I’m in no doubt a more experienced developer could reduce both versions down even further.) I am not going to read too much into that because it is like comparing apples with oranges but for me it was an interesting observation.

 

Summary

I have surprised myself with how much I have learnt building these and how much fun I had doing so.

Acknowledgements

Javascript and JQuery book by Jon Duckett This is the best book I have read on JavaScript and JQuery and I have no hesitation in recommending this to you.

Debugging JavaScript: Logging

If your JavaScript  executes but not how you expect it to, one method to find out what is going on is to add code to the script that outputs information to the console as the script executes.

Vanilla Logging

The method that most JavaScript developers default to is to use console.log similar to the screen shot below.

20180608_1

Opening the Chrome DevTools (F12) displays the output for this script as:

20180608_2

It doesn’t take many messages to appear before I reach information overload so I use this method sparingly. To assist in such situations the JavaScript Console object has other methods that can be used to help make categories of logging easy to see.

Console.info(), Console.warn() and Console.error()

In order to differentiate between different classes of logging, you can use the .info, .warn and .error methods of the Console object.

Here is the function updated to use these methods, note that the call to each of these are the same as console.log

20180608_3

And the output from the Chrome DevTools console is:

20180608_4-

This output comes from Chrome 67 and note that the first two messages which although use .info() the output is identical to .log(). Unfortunately since Chrome 58 info() and log() are shown identical in the console window. (If you would like to know more this link is a good place to start. The calls to warn and error are shown in red and yellow respectively.

Logging Groups

When reviewing the output from a related set of instructions such as the output from a function, it may help to keep the related information together.  Console.group can be used to help in these situations.
20180608_5-

The console output from this function shows, first collapsed:

20180608_6-

and then expanded:

20180608_7-

Table

Another aid to improve readability, particularly when dealing with a lot of tabular data is to format it into a table using console.table. In example shown, an object is populated with data and then a call is made to console.table passing it the columboEpisodes object.

20180608_8-

The output from the Chrome DevTools console is:

20180608_9-

Assert

The very best method of aiding readability is to only have a message appear in the console if it breaks the expected condition at that point in the script. Console.assert can be used in such circumstances. If the assertion returns true nothing is shown. This can help reduce the noise of what is shown in the console window.

20180608_10

The output of the script is shown below, note that only one message is shown, the one returns false which is the second one, X is not greater than Y.

20180608_11

Acknowledgements

Javascript & JQUERY Book by Jon Duckett

The MSDN pages on the Console Object