Collections

Charles Kozeny-PellingBy Charles Kozeny-Pelling

Charles Kozeny-Pelling is a graduate of the University of Oxford

In the course of a writing a computer program, you will often need to group multiple elements together into a collection of some form. JS++ provides two sorts of collections to help you in these contexts: arrays and dictionaries. They will be the focus of this tutorial.

Arrays

We will begin with arrays. Make a new folder named Collections, and then make a new file named "Collections.jspp". Write in the following code:

string[] friendsArray = ["Anna", "Betty", "Chris", "David"];

This code demonstrates a simple way to create a string array and populate it with four elements. The array is assigned to a variable named friendsArray, which belongs to the type string[]. Notice that the array variable makes specific reference to the type of element that the array can contain: string[] variables can only take arrays of string elements, not arrays of any other kind. If we tried to assign an int array to a string[] variable, our code would not compile.

The elements in an array are ordered and each is given a numerical index, starting at zero and increasing by 1 for each successive element. So in friendsArray, for example, "Anna" is given the index 0, "Betty" is given the index 1, and so on.

It’s useful for each element in an array to have an index, since it makes it possible to access the elements individually. To see how this works, let’s write some code which will display particular elements in friendsArray in an HTML document. Make a second file named "Collections.html" and write in the following:

        <!DOCTYPE html>
        <title>Collections program</title>
        <body>
        <p id="content"></p>
        <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
        <script src="Collections.jspp.js"></script>
        </body>
        </html>
        

Save Collections.html to your Collections folder. Now return to Collections.jspp and add two extra lines to the one you already have:

        external $;

        string[] friendsArray = ["Anna", "Betty", "Chris", "David"];
        $("#content").append(friendsArray[0] ?? "", " ", friendsArray[2] ?? "");
        

Look at the last line here, and in particular the expressions friendsArray[0] and friendsArray[2]. These expressions are used to access the array elements at index 0 and index 2 (the first and third elements of the array, given that the index numbering starts from zero). If you compile your code and open Collections.html in a browser, you will see that it displays "Anna Chris".

You'll also notice ?? "" after the array accesses. This will be covered in the next chapter, "Nullable and Existent Types", by Roger Poon. At this time, you only need to know that it is used for providing a default value (an empty string) in case the element is missing.

You can also use an array index to change the element at that index. For example, suppose that after creating our array, we want to change the second element to "Brian". We can do that by writing:

friendsArray[1] = "Brian";

Jagged arrays

JS++ also allows you to create so-called jagged arrays (also known as arrays of arrays): arrays that contain other arrays as elements. For example, we might want to create an array whose elements are string arrays. We could do that as follows:

string[][] jaggedArray = [["Anna", "Betty"], ["Chris", "David"]];

To access one of the inner arrays in jaggedArray, you would use the same syntax as before: jaggedArray[1] would return the array containing "Chris" and "David", for example. To access an element within one of the inner arrays, you would need to specify two indices: the first to indicate the inner array, and the second to indicate the specific element in that inner array. For example, jaggedArray[1][0] would return "Chris", while jaggedArray[0][1] would return "Betty".

Iterating over arrays

When using arrays, you will often want to iterate over their elements. There are two main ways to do this. The first is to use a regular for loop, of the sort we looked at in chapter 5:

        string[] friendsArray = ["Anna", "Betty", "Chris", "David"];
        for (int i = 0; i < friendsArray.length; ++i) {
            $("#content").append(friendsArray[i] ?? "", " ");
        }
        

Notice the condition clause of the for loop, which uses the expression friendsArray.length. This expression returns the number of elements in friendsArray, so it makes sense to use the expression to limit the number of iterations of the loop.

length is an example of a so-called "getter method". A method is a function that belongs to a particular class, and a getter is a particular kind of method which can be called without using parentheses. We’ll look in more detail at methods (getters and other kinds) and classes in chapters 12-27. The length method belongs to the Array<T> class, which makes it available to use on arrays. We’ll look at some of the other methods in the Array<T> class later in the tutorial.

Note: Methods in the Array<T> class are available to use on primitive arrays (of the sort we’re examining in this tutorial) due to a process known as autoboxing. Autoboxing happens when a primitive value is automatically converted into an instance of an associated "wrapper" class. In this context, when you use a method such as length on a primitive array, the primitive is autoboxed into an instance of the Array<T> wrapper class, which allows the method to be used. We’ll cover autoboxing in more detail in later chapters.

The other main way to iterate over an array is to use a foreach loop:

        string[] friendsArray = ["Anna", "Betty", "Chris", "David"];
        foreach (string name in friendsArray) {
            $("#content").append(name, " ");
        }
        

A foreach loop such as this is easier to write than a regular for loop, but it doesn’t give you access to each element’s index in the way that a regular for loop does. So when deciding which kind of loop to use, it will be important to consider whether you need access to the array indices.

Arrays and variadic parameters

In chapter 6, we noted that functions can have a variadic parameter, which allows the function to take infinitely many arguments for that single parameter. When the arguments are given to the function, they are stored as an array. Here is an example of a function with a variadic parameter.

        int add (...int numbers) {
            int total = 0;
            foreach (int number in numbers) {
                total += number;
            }
            return total;
        }
        $("#content").append(add(1, 2, 3));
        

The add function is declared with the variadic parameter ...numbers. When the function is called, it is given the arguments 1, 2, and 3. These arguments are stored as an array named numbers, which then becomes available to be accessed in the function’s body. In this example, we loop over the elements in the array and then return their sum.

Note: A function can’t have more than one variadic parameter.

Array methods

Earlier in the tutorial, we looked at the length method in the Array<T> class, which returns the number of elements in an array. The Array<T> class contains many useful methods, in addition to length, and in this section we’ll look briefly at some of the central ones: indexOf, sort, push, and pop.

The indexOf method returns the first index of a search element, or -1 if the element could not be found in the array:

        string[] friendsArray = ["Anna", "Betty", "Chris", "David"];
        $("#content").append(friendsArray.indexOf("David"));
        

The sort method can be used to sort an array, if the elements in the array are sortable. (For more on sortability and sorting behaviors, see here: the sort method.) For example, we could sort an int array in numerically ascending order like this:

        int[] numbersArray = [7, 2, 9, 5];
        numbersArray.sort();
        foreach (int number in numbersArray) {
            $("#content").append(number, " ");
        }
        

To add one or more elements to the end of an array, you use the push method:

        int[] numbersArray = [7, 2, 9, 5];
        numbersArray.push(6, 5);
        foreach (int number in numbersArray) {
            $("#content").append(number, " ");
        }
        

To remove the last element in an array, you use the pop method:

        int[] numbersArray = [7, 2, 9, 5];
        numbersArray.pop();
        foreach (int number in numbersArray) {
            $("#content").append(number, " ");
        }
        

For a full list of methods in the Array<T> class, see here:

Methods in the Array<T> class

Dictionaries

Dictionaries are a different kind of collection from arrays. The main difference is that whereas arrays contain individual elements, dictionaries contain key-value pairs. Let’s take a look at some code which creates a JS++ dictionary. Before you write the new code, delete the code you already have in Collections.jspp. Now write in the following:

        import System;

        Dictionary<int> friendsAges = {"Anna": 47, "Betty": 28, "Chris": 35, "David": 54};
        

On the first line, you import the System module. We won’t cover the System module in detail in this chapter, but for now the key point is that this import statement lets you use the Dictionary<T>class, which is in the JS++ Standard Library. (We will cover the JS++ Standard Library in later chapters.) Without the import statement, the code that comes after would not compile.

With the import statement in place, however, your code does compile and it creates a dictionary that stores friends’ names and their ages in a key-value format. For each key-value pair, the key is the person’s name and the value is their age. The dictionary’s type is Dictionary<int>, since the value in each key-value pair is an int. We don’t need to specify the key type, in addition to the value type, since the key type in any dictionary must always be string.

Note: When writing the keys for a JS++ dictionary, it’s optional to use quotation marks. So for example, instead of writing Dictionary<int> dict = {"a": 1}; you could also write Dictionary<int> dict = {a: 1}; The compiler knows that your keys must be strings, so the quotation marks will be implicitly assumed if you leave them out.

A dictionary’s key-value pairs are not ordered and they are not assigned an index. To access a particular pair, you use its key. For example, if we wanted to display Anna’s age and Chris’s age in our HTML document, we could do so like this:

        import System;
        external $;
            
        Dictionary<int> friendsAges = {"Anna": 47, "Betty": 28, "Chris": 35, "David": 54};
        $("#content").append(friendsAges["Anna"] ?? 0, " ", friendsAges["Chris"] ?? 0);
        

The expression friendsAges["Anna"] returns the value corresponding to "Anna", and the expression friendsAges["Chris"] returns the value corresponding to "Chris". So if you compile this code and open Collections.html in a browser, your document will display "47 35".

You can also use a key to change the value of a key-value pair:

friendsAges["Anna"] = 48;

This changes the value corresponding to "Anna" to 48. It doesn’t insert a new key-value pair into friendsAges, because a dictionary cannot have two pairs with the same key. To insert a new pair into the dictionary, you would have to use a different key:

friendsAges["Emily"] = 39;

Iterating over dictionaries

It’s easy to iterate both over the keys and over the values of a dictionary. To iterate over the keys, you use a for...in loop:

        Dictionary<int> friendsAges = {"Anna": 47, "Betty": 28, "Chris": 35, "David": 54};
        for (string name in friendsAges) {
            $("#content").append(name, ": ", friendsAges[name] ?? "", ", ");
        }
        

The simplest way to iterate over a dictionary’s values, by contrast, is to use a foreach loop:

        Dictionary<int> friendsAges = {"Anna": 47, "Betty": 28, "Chris": 35, "David": 54};
        foreach (int age in friendsAges) {
            $("#content").append(age, " ");
        }
        

Dictionary methods

Earlier we saw that the Array<T> class contains many useful methods which you can use on arrays. Similarly, the Dictionary<T> class contains various methods which you can use on dictionaries. In this section, we will look briefly at three of the most important ones: length, contains, and remove.

The length method works exactly how you would expect it to, given the behavior of the corresponding method in the Array<T> class: it returns the number of key-value pairs in the dictionary:

        Dictionary<int> friendsAges = {"Anna": 47, "Betty": 28, "Chris": 35, "David": 54};
        $("#content").append(friendsAges.length);
        

The contains method can be used to check whether a dictionary contains a certain key:

        Dictionary<int> friendsAges = {"Anna": 47, "Betty": 28, "Chris": 35, "David": 54};
        if (friendsAges.contains("Anna")) {
            $("#content").append("Anna found!");
        } 
        else {
            $("#content").append("Anna not found!");
        }
        

The remove method can be used to remove a particular key and its associated value from a dictionary:

        Dictionary<int> friendsAges = {"Anna": 47, "Betty": 28, "Chris": 35, "David": 54};
        friendsAges.remove("Anna"); 
        for (string name in friendsAges) {
            $("#content").append(name, " ");
        }
        

For a full list of methods in the Dictionary<T> class, see here:

Methods in the Dictionary<T> class