UserGuide

Collections of Data

From Xojo Documentation

Programs often have a lot of data to manage. Two common techniques for managing data include arrays and dictionaries. Although they both store large collections of information, they do so in different ways.

Arrays

You declare an array by specifying the index of the last element of the array. The index that you specify in the Var statement is actually one less than the number of elements in the array because arrays always have an element at position zero (0). Such an array is sometimes referred to as a zero-based array. Since arrays are zero-based, this statement creates a String array with eleven (11) elements:

Var names(10) As String

This statement creates an array with one element, element zero:

Var names(0) As String

In other words, you declare a variable as an array simply by adding the index of the last element to the Var statement. The index of the last element must be either a number or a constant. You cannot use variables with this syntax.

Const kSize As Integer = 10
Var names(kSize) As String

If you don’t know the size of the array you need at the time you declare it, you can declare it as a null array, i.e., an array with no elements. You do this by using an index of -1 in the Var statement or leave empty parentheses. This means “an array of no elements.” These two examples create an array with no initial elements:

Var firstName(-1) As String
Var lastName() As String

Since the array does not have any elements, you'll have to actually add elements to it. You can do this by resizing it using the ReVar statement or by adding elements to it using the Array method (at assignment) or by using the Insert or Append methods.

This uses the Array method to populate an array, setting its size to the number of elements specified:

Var values() As Integer = Array(5, 8, 42, 56, 32)

This code uses the AddRow method to add rows to an empty array. This technique is useful when the data to go in the array comes from another source that may vary in size, such as a file or a database:

Var names() As String
names.AddRow("Bob")
names.AddRow("Phil")
names.AddRow("Larry")
// The array now has a size of 2, with indexes 0, 1 and 2.

Multidimensional Arrays

You can create multi-dimensional arrays. For example, a spreadsheet layout can be thought of as a two-dimensional array, rows by columns. Each dimension is referred to by its own index. For example, the elements of an array with two dimensions are referred to by one index for the rows and the other for the columns. The first element in the upper-left corner is element 0,0.

You create a multi-dimensional array by specifying an index for each dimension. For example, this statement creates a two-dimensional array with 3 rows and 11 columns:

Var names(2, 10) As String

You can use constants in Var statements to set the size of an array:

Const kLanguages As Integer = 100
Var names(10, kLanguages) As String

Referring to Array Elements

You refer to an element of an array by placing the desired element in parentheses. This example places the text “Frank” in array element (1,1):

names(1, 1) = "Frank"

Getting the Index of the Last Element

The LastRowIndex method returns the index of the last element of a one-dimensional array. For example:

names.LastRowIndex

The number of elements is one greater than this number, since the array has an element zero.

For example, the following code returns 5 in the variable i:

Var i As Integer
Var names(5) As String
i = names.LastRowIndex
If you need the number of elements, use the Count function.
names.Count

Initializing Arrays

After you have declared an array, you can assign initial values to the elements with the Array function as well as individual assignment statements, such as shown above. The Array function takes a list of values and assigns the values to the elements of the array, beginning with element zero. In other words, it provides the same functionality as separate assignment statements for each element of the array.

For example, the following statements initialize the array using separate assignment statements for each array element:

Var names(2) As String
// Separate assignment statements
names(0) = "Fred"
names(1) = "Ginger"
names(2) = "Stanley"

The following statements use the Array function to accomplish the same thing. Note that you don’t have to declare the exact size of the array in the Var statement.

Var names() As String
names = Array("Fred", "Ginger", "Stanley")

The Array function will add elements to the array as needed.

If you declare the array as a fixed size but don’t specify as many values as elements, the Array function will start with element zero and use as many elements as are specified.

Array Assignment

If you have two arrays of compatible data types, you can assign one array to the other array. Simply use the assignment statement without the parentheses. Here is a simple example:

Var names(2), copyNames(2) As String
names = Array("Fred", "Ginger", "Stanley")
copyNames = names

The last statement assigns the values of all three elements of names to the first three elements of copyNames. If copyNames had fewer elements than names, then additional elements would first be added to copyNames and the assignment of all the elements of names to copyNames would be completed. For example, the following is valid:

Var names(3), copyNames(2) As String
names(0) = "Fred"
names(1) = "Ginger"
names(2) = "Tommy"
names(3) = "Woody"
copyNames = names

After the code runs, the copyNames array has a fourth element for storing the value “Woody”.

It is important to understand that when you copy an array like this, both variables are essentially pointing to the same array contents. Changing an element in copyNames would also change the same element in the original names array.

If you need to actually make a copy of the individual elements to a new array, then you will have to loop through and copy each element one by one:

Var names() As String = Array("Fred", "Ginger", "Tommy", "Woody")
Var copyNames() As String

For i As Integer = 0 To names.LastRowIndex
copyNames.AddRow(names(i))
Next

Resizing Arrays

There are several ways to resize arrays after they have been created.

AddRow: The AddRow method adds an element to a one-dimensional array, increasing its size by one. You pass the value you want to add to the array when you call AddRow. For example, the following statement adds an element to the array names and sets the value of this element to the string, “Dave”:

names.AddRow("Dave")

AddRowAt: The AddRowAt method creates an additional element in a one-dimensional array and inserts it in the place you specify. It takes two parameters, the index of the element to be inserted and the value of the new element. For example:

names.AddRowAt(9, "Hal")

After this statement runs, the value of names(9) would be “Hal”. The old element(9) would be shifted up to element(10) and so forth. The size of the array would be increased by one, as with AddRow.

RemoveRowAt: The RemoveRowAt method removes the element whose index you specify. This example removes the element with index 9, decreasing the size of the array by one and shifting the array elements after the removed element down by one:

names.RemoveRowAt(9)

ResizeTo: The ResizeTo method resizes an existing array. You pass the new values of the array’s indexes but you don’t specify the data type, which is set by the initial Var statement. This example resizes the array names to 101 elements:

names.ResizeTo(100)

ResizeTo works on both one- and multi-dimensional arrays. For multi-dimensional arrays, you can only resize the existing dimensions; you cannot add or reduce the number of dimensions themselves.

A difference between Var and ResizeTo is that Var accepts only integers or constants, while ResizeTo accepts any expression that returns an Integer. This includes, for example, a user-written function that returns an Integer value or a simple variable. Using this feature, you can dimension your arrays on-the-fly.

If you don’t know the size of the array you need at the time you declare it, you can declare it as a null array, i.e., an array with no elements, and use the ReVar command to resize it later. If your program needs to load a list of names that the user enters, you can wait to size the array until you know how many names the user has entered. You can write a function to figure out what that number is and use it with ResizeTo or use the AddRow methods to add the required elements to the array one-by-one.

If you need to quickly remove all elements of an array, use the RemoveAllRows method.

names.RemoveAllRows

Converting to and from an Array to Variables

Two functions enable you to take a take an array and break it up into separate variables and take a single string variable and convert it into an array.

ToArray: This function takes a String variable and creates a one-dimensional array by dividing the string up into elements separated by a delimiter. The delimiter is a character or series of character that signals the end of one element and the start of the next element. By default, the delimiter is a space, but you can specify another delimiter.

Here is an example that divides up the contents of a string into array elements. It specifies the comma as the delimiter. After this call, the resulting array, names, has three elements:

Var names() As String
// Convert using the ToArray method
Var s As String
s = "Juliet,Taylor,Casting"
names = s.ToArray(",")
// names(0) = "Juliet"
// names(1) = "Taylor"
// names(2) = "Casting"

FromArray: This method does the opposite of ToArray. It takes a one-dimensional array and returns a string containing all the elements separated by the specified delimiter. This example takes an array and returns its contents as a single text variable:

Var names(2) As String = Array("Bob", "Phil", "Larry")
Var s As String
s = String.FromArray(names, ",") // t = "Bob,Phil,Larry"

Sorting Arrays

You may need to sort the contents of an array, which you can easily do using the Sort method:

Var names(2) As String = Array("Betty", "Phil", "Linda")
names.Sort
// Names now contains: Betty, Linda, Phil

For more complicated sorting needs, you can use the SortWith method to sort an array and keep the contents of two or more other arrays in sync with the now sorted first array. This is useful when you have multiple arrays of related information and want to sort one of the arrays, but also ensure the data in the other arrays are still correctly related to the newly sorted array.

As an example, you have one array called names and another called zips defined like this:

Var names() As String = Array("Mozart", "Bing", "Jackson", "Flintstone")
Var zips() As String = Array("04101", "04240", "04123", "04092")

Now if you were to sort just names, the index for "Bing" will change from 1 to 0. But the zips array has not changed, so its corresponding zip will no longer be correct because zip(1) is "04240", but zip(0) is "04101". What you want to do is to also re-arrange zips so that its contents continue to match the newly sorted names array.

You do this by using the SortWith method to sort the names array like this:

Var names() As String = Array("Mozart", "Bing", "Jackson", "Flintstone")
Var zips() As String = Array("04101", "04240", "04123", "04092")

names.SortWith(zips)

// names() = "Bing", "Flintstone", "Jackson", "Mozart"
// zips = "04240", "04092", "04123", "04101"

As you can see, the zips array has its contents adjusted so that "04240" remains related to the new position for "Bing".

Lastly, you can also implement your own sorting method to sort an array of classes. This is useful when your array consists of Classes, rather than simple data types such as String or Integer.

Dictionary

A Dictionary is an object that is made up of a list of key-value pairs. That is, each value is paired with an identifying key. The interesting feature of Dictionaries is that both the key and the value are a Variant so they can contain a value of any data type. This means that a dictionary can store a mixture of data types — and that the key doesn’t have to simply be an integer. You use the key to look up a value in a Dictionary or you can loop through the values.

A Dictionary is a great way to have fast lookups of information and can be considerable faster than a large array.

Although technically a class (and classes are not described until later in the User Guide), Dictionary is so commonly used that it is worth covering here as a data type.

As a class, you have to create an instance with the New command before you can use a Dictionary:

Var d As New Dictionary

You add values to the Dictionary using the Value method to specify a key name and assign it the value:

d.Value("FirstName") = "Julie"

You can look up a value using the key:

Var name As String
name = d.Value("FirstName")

Once you have a Dictionary populated with values, you can iterate through them using a For Each...Next loop. This loops through the Dictionary to get the keys and then uses the key to lookup the value:

Var pets As New Dictionary
pets.Value("Cat") = "Shawmut"
pets.Value("Dog") = "Seltzer"
pets.Value("Gerbil") = "Topher"

For Each key As Variant In pets.Keys
Var value As String = pets.Value(key)
TextArea1.Value = TextArea1.Value + key + " is " + value + ", "
Next

For iOS projects, you use the Xojo.Core.Dictionary class instead. It works similarly, but looping through the contents works slightly differently:

Var pets As New Xojo.Core.Dictionary
pets.Value("Cat") = "Shawmut"
pets.Value("Dog") = "Seltzer"
pets.Value("Gerbil") = "Topher"

For Each entry As DictionaryEntry In pets
TextArea1.Text = TextArea1.Text + entry.Key + " is " + entry.Value + ", "
Next

Pair

The Pair class is similar to the Dictionary. It has two properties: Left and Right. Thus, each Pair instance consists of a key-value pair. As it the case with the Dictionary, the values in the pair are variants. You use the “:” operator to assign the Left and Right values when the Pair is declared.

For example:

Var p As Pair = "Telephone Number" : "(406) 737-8946"

This assigns “Telephone Number” to the Left property of the pair and the value of the number to the Right property, which you can access like this:

Var kind As String = p.Left
Var phone As String = p.Right

It also can store a linked list of pairs when it is passed a list of items, such as:

Var p As Pair = 1 : 2 : 3 : 4 : 5

The first pair consists of the pair “1” (Left property) and the second pair object (Right property); the next pair consists of the “2” and the third pair, and so forth.

Pair is not available for iOS projects.

See Also

Dictionary, Pair classes; Arrays topic; Array, Var, Arrays.ResizeTo commands