Issue 57 * September 26 2008

Arrays Examined
Get your head round the new style arrays

by Tom Healy

Arrays are an extremely efficient way of storing, ordering and moving data around. Unfortunately, to a new user, it may be a little unclear what arrays actually are and how they can be used, so in this newsletter I will attempt to go through why they are useful and how they can be deployed in Revolution. I'll also be going through Revolution 3.0's expanded array capabilities ie. multi dimensional arrays.

So let's begin by looking at how Revolution has dealt with arrays prior to version 3.0. Simply put an array is like a table that allows you to store data and access it quickly. In the past they have always been one dimensional. The array is made up of keys and each key contains an item of data, like a table of variables. Each key can be given a specific name to identify its contents. Here is a simple example of one:

Key Names Contents
Fruit Apple
Cereal Cornflakes
Veg Carrot
Drink Lemonade

So you have the key names on the left that describe the contents of their elements. Overall this array represents a fairly simple and frugal shopping list. You could construct this in Revolution by performing the following:

// An array can be declared just like any other variable in
-- revolution
local tShoppingList
put "Apple" into tShoppingList[Fruit]
put "Cornflakes" into tShoppingList[Cereal]
put "Carrot" into tShoppingList[Veg]
put "Lemonade" into tShoppingList[Drink] 

So the name of the key you wish to place the data into always goes inside the square brackets on the right. You don't need to declare new keys, they are simply created as soon as you place data into them. Although I've put the data into the array above in a specific sequence, the data actually has no order in the array. The only structure is imposed by the key names. To access the data stored in the array you refer to the appropriate key eg.

local tResult
put tShoppingList[Fruit] into tResult 

tResult now contains "Apple". As mentioned before there is no sequence to the data stored, however an order can be imposed by making use of the "the keys" of the array. The keys returns a return delimited list of the keys of the array eg.

local tKeys
put the keys of tShoppingList into tKeys 

tKeys now contains the following:

Fruit
Cereal
Veg
Drink

This variable can now be used for the purposes of outputting the array contents in some kind of sequence by using a repeat loop:

// Here we are using the "for" form of the repeat syntax
repeat for each line tKey in tKeys
   put tShoppingList[tKey] & return after msg
   // here we've used msg as an abbreviation for the message box
end repeat

// Alternatively we could have referred to the keys direclty
repeat for each key tKey in tShoppingList
   put tShoppingList[tKey] & return after msg
end repeat 

Both of these will produce the following ouput in the messagebox:

Apple
Cornflakes
Carrot
Lemonade

Although the keys property returns a list in no specific sequence the list can then be sorted to impose an order upon the array contents. For example we could sort the keys alphabetically and then perform the same repeat loop as follows:

local tKeys
put the keys of tShoppingList into tKeys
sort lines of tKeys ascending text
// tKeys is now alphabetically ordered - Cereal,Drink,Fruit,Veg
// see documentation of sort for further ordering options
repeat for each line tKey in tKeys
   // We've output the key name aswell for clarity
   put tKey & ":" && tShoppingList[tKey] & return after msg
end repeat

Producing the following:

Cereal: Cornflakes
Drink: Lemonade
Fruit: Apple
Veg: Carrot

So now we have a way of storing, accessing and sorting data into arrays. However, the method for inputting we have demonstrated here is a little laborious. It is far quicker to take a list of data and then use a repeat loop or the split command to populate the array. Split automatically populates the keys and contents of an array when given a list of data to operate upon eg.

local tList
put "cereal cornflakes,drink lemonade,fruit apple,veg carrot" \
into tList
split tList by comma and space 

tList now contains an identical array to the one used in the earlier examples. The split command requires a variable that is not an array, containing a list of data, as its first argument. It then requires a primary and optionally a secondary delimiter. The delimiters determine where the split command chooses to split the contents of the variable and place it into the new array. The primary delimiter here is comma and specifies what will be placed in the array contents. The secondary delimiter here is space and specifies what will be used as the key names for the array. Combining this method with list fields and making use of the selectedText of each field to form the contents of the variable to pass to the split command can be a very quick way of populating arrays.

The contents of an element of the array can be anything, even another comma delimited list. However once you begin to subdivide the contents of each array element you may find it more efficient and useful to make use of Revolution 3.0's new support for multi-dimensional arrays. So now let's overview what new features are now supported.

In version 3.0 the power of arrays has really been unlocked for the first time in Revolution. Previously, once the contents of the arrays were stored, they had to remain within their local scope ie. if an array was a command local it could not be passed as a parameter, or sent to any other function or command for use elsewhere. This was a considerable constraint upon their use. Now however, arrays can not only be passed as single parameters to other commands/functions but can also be stored as custom properties of objects.

So for example, the code we have looked at so far constructs a simple and highly nourishing shopping list. If this were in a script it might have been located in a command such as "makeShoppingList". But once the list is constructed we may wish to perform further actions with this list such as print it out. In order to achieve this we need to pass the array as a parameter:

// Command for constructing the array
command makeShoppingList
   local tList
   put "cereal cornflakes,drink lemonade,fruit apple,veg carrot" \
   into tList
   split tList by comma and space
   // Now pass the array to the printing command
   printArray tList
end makeShoppingList

// Command to print out the contents of an array, accepts an
// array as its parameter
command printArray pArray
   local tKeys, tText2Print
   put the keys of pArray into tKeys
   sort lines of tKeys ascending text
   // Place the contents of the array in a text string ready to
   -- print
   repeat for each line tKey in tKeys
      put tKey & ":" && tShoppingList[tKey] & return after \
      tText2Print
   end repeat
   // revPrintText accepts a string as its parameter
   revPrintText tText2Print
end printShoppingList

This is a simple example but the potential for the use of arrays is dramatically improved now that they can be passed around your programs as simply as variables. An array can be stored as a custom property of an object in an equally straight forward way:

set the cStoredArray of this card to tArray 

This is a good way of preserving the contents of something, be it a variable or an array, outside the scope of a specific script. This makes it easy to access the stored data from anywhere else in your program by simply querying the custom property:

put the cStoredArray of this card into tArray

Custom properties can be set on all gui objects in rev, buttons, scrollbars, cards, stacks, fields . . . you get the idea.

Finally we're going to have a look at the introduction of multi-dimensional arrays in 3.0, which I assure anyone who might not be familiar with them, are far less intimidating than they sound. The easiest way to think about a MD array is that it is an array whose contents can also contain arrays. This nesting of arrays can be performed, in theory an arbitrary number of times ie. arrays of arrays of arrays of arrays . . . I wouldn't like to put my use of the word arbitrary here to the test though.

So to follow on the imaginative and exciting theme of shopping lists we can now increase the complexity of the array we constructed earlier to include days, weeks months etc.

local tMonthly
local tWeekly

local tMonday
put "cereal cornflakes,drink lemonade,fruit apple,veg carrot" \
into tMonday
split tMonday by comma and space
put tMonday into tWeekly["monday"]

local tTuesday
put "cereal branflakes,drink cola,fruit orange,veg turnip" into \
tTuesday
split tTuesday by comma and space
put tTuesday into tWeekly["tuesday"]

local tWednesday
put "cereal ricepops,drink milk,fruit banana,veg broccoli" into \
tWednesday
split tWednesday by comma and space
put tWednesday into tWeekly["wednesday"]

. . .

put tWeekly into tMonthly["Nov"]["Week1"]

I've gone through the steps explicitly here to try and make it as clear as possible what we are producing, I'm a little doubtful about how many people will actually plan out their daily shopping months in advance using arrays and also survive on just a drink, a bowl of dry cereal, a piece of fruit and a vegetable every day. A more sophisticated method involving repeat loops and an initial long string containing all the data could be employed. Here is a tree representation of what this array looks like, I've varied the indent to signify the nesting level of each element of the array:

Nov -
   Week1 -
      monday -
         drink : lemonade
         fruit : apple
         veg : carrot
         cereal : cornflakes
      tuesday -
         drink : cola
         fruit : orange
         veg : turnip
         cereal : branflakes
      wednesday -
         drink : milk
         fruit : banana
         veg : broccoli
         cereal : ricepops
If I was curious as to exactly what kind of cereal I planned to buy on the Wednesday of the first week of November i could use the following command:

put tMonthly["Nov"]["Week1"]["tuesday"]["cereal"] 

Which would output "branflakes" into the message box. So that's a brief introduction into arrays and how to use them in Revolution. Admittedly a shopping list planner is a slightly uninspired use of such a powerful tool but I hope it has served its instructive purpose and given you some pointers on the new array features in Revolution 3.0!

Main Menu What's New