JavaScript - Lesson 5, ArraysLesson objectivesThe best way to think of an array is as a series of pigeon-holes. Each pigeon-hole, or element of the array, can hold one value - string or number - just as an ordinary variable can. The array has a name, just like an ordinary variable, and you get access to the elements using a different positive number for each one (0 for the first one, 1 for the second, 2 for the third etc.) The numbers used are called the indices of the array. Here's an example - a one-dimensional array which I shall call myArray (for want of a better name): The array is declared as follows: var myArray = new Array(); The individual elements are set up as follows: myArray[0] = 41; myArray[1] = -5; myArray[2] = 20; // etc. The others are set up similarly You'll notice that the array, unlike a simple variable, has to be declared using the word new followed by the word Array and then a pair of parentheses. There is no way of getting round this. However, there is an alternative way to set the values in the array elements. Just as ordinary variables can be set to values at the same time as they are declared, you can do the same with arrays: var myArray = new Array(41, -5, 20, 0, 3, -11, 37); The elements must be enclosed within square brackets [] rather than round ones (). The elements of the array can be used anywhere where a normal number can be used. For instance, all the following are perfectly legal: alert("The value is " + myArray[4]); x = 2 * myArray[i] + myArray[3 * count - 6]; myArray[j] = myArray[j-1] + myArray[j+1]; From this you will see that:
You can use any array value that has been already set up. Here, for instance, is another array: var another = new Array(); another[3] = -45.6; another[5] = "Richard"; This example shows you that arrays can hold numbers in some elements and strings in others! In this case alert(another[3]); alert(another[5]); will produce the values that you expect. However, the instruction alert(another[4]); will produce the special value NaN, which isn't really a number or a string, but stands for "Not A Number". This is because another[4] hasn't been assigned to a string or numeric value yet. Arrays are often used with for loops and other loops. Here is a for loop that displays the contents of an array on the screen with a paragraph break between each element: for (x = 0; x < 10; x++) { document.write(values[x]); if (x < 9) document.write("<P>"); } The if statement is in there to ensure that there is no paragraph break after the last element of the array has been displayed. Here is another loop that adds together all the elements of an array - but ignores all the ones that aren't divisible by 5: var sum = 0; // The sum starts off at 0 count = 0; do { if (listOfNumbers[count] % 5 == 0) sum += listOfNumbers[count]; // Add the value to the sum count++; } while (count < 83); That could probably have been written more succinctly using a for loop, but I like to ring the changes. Just because array elements start at 0 doesn't mean that you have to use every element. You may come across a problem where you need array elements from 100 to 120 only. In that case, simply ignore the elements that you don't need! Two- and multi-dimensional arraysThe arrays that we have been looking at so far are one-dimensional arrays - the values stretch out in a line. We can also declare and use two-dimensional arrays: In this case, since we have rows and columns, we need two numbers to specify an elements of the array. If we have declared an array called twoDimGrid, then it could be accessed as follows: twoDimGrid[0][0] = 34; twoDimGrid[2][4] = 30; twoDimGrid[1][5] = 20; // etc. Declaring and using two dimensional arrays is done in a similar way to one-dimensional arrays, except that each column of the array must be declared individually: var twoDimGrid = new Array(); // This declares the array itself twoDimGrid[0] = new Array(); // This declares the first column twoDimGrid[0][3] = 31; // Now we can use the elements in the first row twoDimGrid[0][6] = twoDimGrid[0][3] - 32; twoDimGrid[2] = new Array(); // This declares the third column twoDimGrid[2][6] = 26; // Now we can use the elements in the third column Each column must be declared using the new Array() instruction separately, but they needn't be declared in order, and you can easily miss some of them out if you don't need those elements (e.g. we didn't declare the second column in the example above). You will also notice that the only var command is needed for the initial declaration - you don't need one when you declare each column. Probably the easiest way to declare all those columns is to use a loop: var square = new Array(); var count; for (count = 0; count < 7; count++) square[count] = new Array(); // This declares each column in turn The first iteration of the loop declares square[0] as an array, the second iteration declares square[1] as an array, the third iteration declares square[2] as an array etc. At the end of the loop, the array has 7 columns (numbered from 0 to 6 etc.), although there is nothing to stop you adding more later. Then you can manipulate the elements to your heart's content. Similarly, there is nothing to stop us using a declaring arrays with as many dimensions as we like (subject only to memory requirements). The following example shows a three-dimensional array: This is set up in a similar way: var cube = new Array(); cube[0] = new Array(); // This gives us a two dimensional array cube[0][0] = new Array(); // This gives us a three dimensional array cube[0][0][3] = "Hello"; // This is how we use a three dimensional array Of course, we would have to go through a lot more commands to get all the rows and columns set up. Assigning arrays - a warningHere we have a small program which declares two arrays - one called first, the other called second. The elements of first are set up so that they hold the numbers 1, 2, 3, etc. and then, the program copies every element of first into second. With me so far? Right ... var first = new Array(); for (count = 0; count < 100; count++) first[count] = count; var second = new Array() for (count = 0; count < 100; count++) // Copying! second[count] = first[count]; // Copying! In this case, first[50] holds the value 50, and second[50] holds the value 50 as well, as you might expect. The following instruction alters the vale of first[50]: first[50] = 345.112; document.write("The value of first[50] is " + first[50] + "<BR>"); document.write("The value of second[50] is " + second[50] + "<BR>"); The instructions display: The value of first[50] is 345.112 The value of second[50] is 50 However, suppose we had altered the part of the program where the elements are copied from first to second (the lines marked Copying! In the program above) to this: second = first; This will also make the elements of second be the same as first. However, re-running the program produces the following output: The value of first[50] is 345.112; The value of second[50] is 345.112; Although we have only altered the value of first[50], the value of second[50] has changed also. What has happened? Well, in fact, the statement second = first has made both the variables second and first point to the same set of numbers. Instead of being two separate variables, there is only one copy of the numbers with two variables pointing to it. If you want two separate copies of the numbers, use the first method of copying the elements. If you want two ways of accessing the same elements, use the second way. Array properties and methodsAs you can see, arrays are not like your average variables! In fact, they are objects. You will remember from the first lesson that pretty much everything in JavaScript is an object - with properties (pieces of information associated with them) and methods (small groups of instructions) associated with them. Arrays also have properties and methods. lengthThe length property gives 1 more than the highest index of a declared value in the array. This means that if you declared an array called stockName and set up values as follows: var stockName = new Array(); stockName[4] = "Fluffy Soap"; stockName[7] = "Wizzo Flakes"; document.write(stockName.length); The value displayed on the screen is 8, because the highest defined index is 7, even though only two of those elements are defined. When there are no gaps in the elements defined, the length property gives you the number of elements in the array (remember, the first element is 0, so the number of elements would be one more than the highest index) - which is why it is called the length. This can be useful if you can't remember how many elements there are in the array, or the number of elements is liable to change. For instance, to add the elements of the array, the code would be: sum = 0; for (x = 0; x < myArray.length; x++) sum += myArray[x]; In this case, we don't need to know the length of the array in advance, the length property will fill that number in automatically. sort()This is a method built into arrays which sorts them into ascending order. The command is used as follows: myArray.sort(); There is no need for special assignment here. However, be warned! The array assumes that the elements of the array are strings, even if you have filled it entirely with numbers. This means that they are sorted alphabetically. An alphabetic sort looks at the first letter of the words (and numbers are counted as words in this case) and only looks at the second letter of the words if the first one is not enough to distinguish them. This means that the number 7 is alphabetically before 8, but alphabetically after 64. The computer looks at the "7" and the "6" of the 64 and sorts them just on the basis of those two "letters". Here's an example: <script> var x = new Array (7, 2, 3, 22, 71, 30); var count; x.sort(); for (count = 0; count < x.length; count++) document.write(x[count] + "<br />"); </script> In this case, the output is as follows: 2 22 3 30 7 71 You see that, alphabetically speaking, both 2 and 22 come before 3, simply because "2" comes before "3" in the extended alphabet that computer programs use. Similarly, "3" comes before "7" in that alphabet, so 7 comes later in the list than both 22 and 30. How do we overcome this problem?Well, the obvious way is to write your own function that sorts the array. That way you can sort it numerically if it contains numbers. This is shown in Example 5a, and you can simply copy the function from that example and use it unaltered in your own programs. However, there is an easier (but clumsier) way. You may have spotted that it is numbers less than 10 that cause the problem. If we add a character "0" to the start of the numbers which are less than 10, then the numbers are sorted properly. Here is the previous example, with "0" added where necessary: <script> var x = new Array (7, 2, 3, 22, 71, 30); var count; for (count = 0; count < x.length; count++) if (x[count] < 10) x[count] = "0" + x[count]; x.sort(); for (count = 0; count < x.length; count++) document.write(x[count] + "<br />"); </script> 02 03 07 22 30 71 Although we have a "0" on the start of the numbers, they have been sorted correctly. It seems strange that JavaScript treats the elements of array x as numbers when it tests the condition (x[count] < 10), and yet as strings when it performs x.sort(). Aren't computers peculiar! Don't add "0" to the start of all the numbers, otherwise you will be back to where you started and they will not be sorted correctly. Instead, only add "0" as necessary at the beginning to make sure that all the numbers are two "letters" long. Of course, if you have numbers which go into three or more digits, then you may need to add "0" or "00" or even "000" to the numbers as appropriate. This is demonstrated in Example 5b. Personally, I don't like this "adding 0" method. This is because it leads to problems with arithmetic. The trouble is that any number that starts with a "0" digit is interpreted by JavaScript as an Octal (base 8) number - yikes! This means that, although the numbers will sort correctly, as soon as you start performing arithmetic on them, you can into terrible tangles! My advice is to forget the "0" method and use the array to sort the numbers - or simply to stick to lists of numbers where this problem doesn't occur! reverse()This works in a similar way to sort() except that it reverses all the elements. If an array originally contained the values 3, 1, 2, 5, 6 in that order, then the reversed array would contain 6, 5, 2, 1, 3. It is used in a similar way to sort():
myArray.reverse() In this case, the warning about sort() does not apply. JavaScript is simply reversing the order of the elements, not comparing them in any way, so it makes no difference if the array contains strings, numbers or both. |