Recipe 6.9 Storing Complex or Multidimensional Data

6.9.1 Problem

You have two or more sets of related data and you want to be able to keep track of the relationships between the elements.

6.9.2 Solution

Use parallel arrays, an array of arrays (a multidimensional array), or an array of objects.

6.9.3 Discussion

You can create two or more parallel arrays in which the elements with the same index in each array are related. For example, the beginGradientFill( ) method, discussed in Recipe 4.10, uses three parallel arrays for the colors, alphas, and ratios of the values used in the gradient. In each array, the elements with the same index correspond to one another.

To create parallel arrays, populate multiple arrays such that the elements with the same index correspond to one another. When you use parallel arrays, you can easily retrieve related data since the indexes are the same across the arrays. For example:

```colors = ["maroon", "beige",    "blue",     "gray"];
years  = [1997,     2000,       1985,       1983];
makes  = ["Honda",  "Chrysler", "Mercedes", "Fiat"];

// Loop through the arrays. Since each array is the same length, you can use the
// length property of any of them in the for statement. Here, we use makes.length.
for (var i = 0; i < makes.length; i++) {
// Outputs:
// A maroon 1997 Honda
// A beige 2000 Chrysler
// A blue 1985 Mercedes
// A gray 1983 Fiat

// Display the elements with corresponding indexes from the arrays.
trace("A " + colors[i] + " " + years[i] + " " + makes[i]);
}```

Another option for working with multiple sets of data is to create a multidimensional array, which is an array of arrays (i.e., an array in which each element is another array):

```// Create an array, cars, and populate it with elements that are arrays. Each element
// array represents a car and contains three elements (make, year, and color).
cars = new Array(  );
cars.push(["maroon", 1997, "Honda"]);
cars.push(["beige", 2000, "Chrysler"]);
cars.push(["blue", 1985, "Mercedes"]);
cars.push(["gray", 1983, "Fiat"]);

// Loop through the elements of the cars array.
for (var i = 0; i < cars.length; i++) {
// The output is the same as in the earlier parallel arrays example:
// A maroon 1997 Honda
// A beige 2000 Chrysler
// A blue 1985 Mercedes
// A gray 1983 Fiat

// Output each element of each subarray, cars[i]. Note the use of two successive
// indexes in brackets, such as cars[i][0].
trace("A " + cars[i][0] + " " + cars[i][1] + " " + cars[i][2]);
}```

Here is another way to view the two-dimensional cars array's contents. This displays the elements in a long list (the formatting isn't as nice as in the previous example, but it shows the array structure more clearly).

```// Loop through the elements of the cars array.
for (var i = 0; i < cars.length; i++) {
// Loop through the elements of each subarray, cars[i].
for (var j = 0; j < cars[i].length; j++) {
// Note the use of two successive indexes in brackets, cars[i][j].
trace("Element [" + i + "][" + j + "] contains: " + cars[i][j]);
}
}```

In the preceding example (the array of arrays), it is hard to discern the meaning of something like cars[i][0] or cars[i][j]. Furthermore, if the order of elements in a subarray changes, we would have to modify our code (or it might erroneously display "A Honda maroon 1997" instead of "A maroon 1997 Honda").

One alternative is to work with related data using an array of objects. This technique is similar to working with an array of arrays, but it offers the advantage of named properties. When you use an array of arrays, you must reference each value by its numbered index. However, when you use an array of objects, you can reference the data by property name instead of index number. We can specify the properties of the object in any order we like, because we'll refer to them later by name, not by number.

```// Create an array, cars, and populate it with objects. Each object has a make
// property, a year property, and a color property.
cars = new Array(  );
// Here, we use object literals to define three properties for each car and then add
// the object literals to the main array.
cars.push({make: "Honda",    year: 1997, color: "maroon"});
cars.push({make: "Chrysler", year: 2000, color: "beige"});
cars.push({make: "Mercedes", year: 1985, color: "blue"});
cars.push({make: "Fiat",     year: 1983, color: "gray"});

// Loop through the cars array.
for (var i = 0; i < cars.length; i++) {
// The output is the same as in the earlier examples, but each value is referenced
// by its property name, which is more programmer-friendly.
trace("A " + cars[i].color + " " + cars[i].year + " " + cars[i].make);
}```