It's Friday. It's 7am. I have at least another half an hour before my higher brain functions begin to react to the coffee. It's tutorial time.

Overview

In this outing I'm going to be looking at the basis of all real programming - arrays. Every programming language uses arrays. An array is a declared variable in a program that can hold many values. The individual values held within the variable are accessed using the ordinal of the values position within the array eg. variable(0). In this instance the ordinal, 0, would return the first (arrays are 0 based) value in the array variable.

Static arrays

Think of a single dimension array as a list. Consider the following snippet:

This snippet declares the array fruit as having 3 values (0 through 2) and sets a value for each ordinal. This is a static array because the number of items that the array hold is fixed by the DIM statement. But in the real world we seldom have a use for static code such as this. More often we want arrays to hold an number of values that can only be determined at runtime.Code:dim fruit(2) fruit(0) = "apple" fruit(1) = "orange" fruit(2) = "banana"

Single dimesion arrays

Let's crete our array of fruits again but this time make it dynamic, so that it can hold an indeterminate number of items.

What just happened? Ok - first we declared our array. Using the syntax above the array is created empty. To add the first item to our list we need to tell the array to make a space for our new value. This is done using the REDIM statement, which re-dimensions the array. By using the PRESERVE keyword we tell the array to remember all previously stored values. If we ommit the preserve keyword any data that already exists in our array is lost.Code:'Declare our array fruit = array 'Add a new value to our array. redim preserve fruit(ubound(fruit)+1) fruit(ubound(fruit)) = "apple" redim preserve fruit(ubound(fruit)+1) fruit(ubound(fruit)) = "orange" redim preserve fruit(ubound(fruit)+1) fruit(ubound(fruit)) = "banana"

We can find out how many values an array holds using the UBOUND keyword. UBOUND(anArray) tells us how many items there are in teh array anArray. Because arrays are 0 based the number of items in a single dimesion array always equals UBOUND(anArray)+1. So the value of fruit(ubound(fruit)+1) will equal 0, the number of items currently held in the array fruit +1. The line fruit(ubound(fruit)) = "apple" sets the new value that we have created (at ordinal 0) in the array to "apple".

Therefore:

means create a new value 1 greater than the current number of items in the array, keeping all the existsing values and:Code:redim preserve fruit(ubound(fruit)+1)

Sets the value of the newly created item.Code:fruit(ubound(fruit)) = "apple"

Multidimensional arrays

You can have arrays with many dimensions. Imagine a 2 dimensional array as a table. Imagine a 3 dimensional array as a cube. Try not to imagine a number of dimensions large than 3 however because it is the prime cause of spontanious human combustion. I think you can have a riduculous number of arrays in VB (20? maybe) but certainly enough that you could never use them. Arrays with more than 3 dimensions are very rarely used because the human mind has difficulty thinking in more than 3 dimensions. If someone ever asks you for more than 3 dimensions ask for mental insurance. You'll need it. But I digress.

Once again let's start with the static version:

Once again this code is not very useful because it is static. So how can we make it dynamic? When using multi dimensional arrays we can still use our UBOUND keyword. With multidimesional arrays the syntax of the UBOUND is slighly different however:Code:'It's a table - 3 cells wide by three cells high 'Think of this as x,y axis dim aTable(2,2) atable(0,0) = "0,0" atable(0,1) = "0,1" atable(0,2) = "0,2" atable(1,0) = "1,0" atable(1,1) = "1,1" atable(1,2) = "1,2" atable(2,0) = "2,0" atable(2,1) = "2,1" atable(2,2) = "2,2"

Where anArray is the array that you wish to find the itemcount for and dimension is the dimension number.Code:UBOUND(anArray,Dimension)

An example. To get the upper bound of our x and y dimensions above we would use the following:

We cannot however us the PRESERVE keyword when re-decalring multi dimesional arrays and so the dynamic version of the above code is a bit more sticky. We can however get round the problem by writing a function that:Code:ubound(aTable,1) ubound(aTable,2)

1...Creates a tempoary array of the right dimensions

2...Copies the old data into the tempoary array

3...Adds the new data to the tempoary array

4...Returns the tempoary array.

The function might look like this:

Code:aTable = array aRow = array aRow = ("Apples","Green","pips") aTable = AppendRecord(aTable,aRow) aRow = ("Oranges","Orange","pith") aTable = AppendRecord(aTable,aRow) aRow = ("Bananas","Yellow","peel") aTable = AppendRecord(aTable,aRow) for y = 0 to UBOUND(aTable,1) for x = 0 to UBOUND(aTable,2) echo aTable(y,x) ' Think (Row,Column) next next Public Function AppendRecord(p_Table,p_Record) temp = array 'p_table is a 2 dimesional array 'p_Record is a 1 dimesional array 'p_record will be treated as a row and added to the 'end of the p_table array 'Create an empty array of correct new dimensions redim temp(ubound(p_Table,1)+1, ubound(p_record)) 'Add the p_Table values to temp for y = 0 to ubound(p_Table,1) for x = 0 to ubound(p_Table,2) 'Copy the value at cell y,x from p_Table to temp temp(y,x) = p_Table(y,x) next next '**Create a new record in the array 'Iterate through fields in passed array adding to the temp array for n = 0 to ubound(p_record) temp(ubound(temp,1),n) = p_record(n) next 'Set the new values in the p_Table Array AppendRecord = temp End FunctionDirectional sorting of 2 dimensional arrays

And now, for those of you who havn't given up, here's an ASP class that I use to sort 2 dimensional arrays (tables). Once you've got your 2 dimensional array (or table) you will probably want to be able to sort it, either into ascending or decending order, and using the column ordinal to sort by. This code is written in a class so that I can instantiate a copy of it for within any other script without re-writting this code.

[b]Usage[b]

Code:SortArray(aArray,OrderBy,Dir) aArray - 2 dimensional array OrderBy - Ordinal of column to sort by - default 0 Dir - Direction to sort in ("ASC"/"DESC") - default "asc"The class file!

Code:<% '<----- VBScript Class By NTSA '<----- www.ntsa.org.uk '<----- Class Name : ArrayCls '<----- Compile Date : 11/09/2002 Class ArrayCls Public function SortArray(aArray,OrderBy,Dir) 'aArray - 2 dimensional array 'OrderBy - Ordinal of column to sort by 'Dir - Direction to sort in (ASC/DESC) 'If sort direction is ommitted or not asc or desc then set to asc dir = lcase (dir) if dir = "" or (dir<>"asc" and dir<>"desc") then dir = "asc" if len(orderby) = 0 then orderby = 0 san = 0 do changed = false for row = 0 to ubound(aArray,1)-1 select case AlphaCompare(aArray(row,OrderBy),aArray(row+1,OrderBy)) case 0 'Both the same case 1 'row row is alpha< than row row+1 IF dir = "desc" then aArray = SwapRows(aArray,row,row+1) changed = true end if case 2 'row row+1 is alpha< than row n if dir = "asc" then aArray = SwapRows(aArray,row,row+1) changed = true end if end select next san = san + 1 loop until changed = false or san = ubound(aArray,1) IF san => (ubound(aArray,1)*ubound(aArray,1)) THEN response.write "failed sanity check! " end if SortArray = aArray end function '************** '**Private functions private function SwapRows(aArray,row1,row2) temp = array 'Copy aArray into a temp variable redim temp(ubound(aArray,1),ubound(aArray,2)) for y = 0 to ubound(aArray,1) for x = 0 to ubound(aArray,2) temp(y,x) = aArray(y,x) next next 'Iterate throgh the colums for n = 0 to ubound(aArray,2) 'Swap to row values temp(row1,n) = aArray(row2,n) temp(row2,n) = aArray(row1,n) next 'Return the new array SwapRows = temp end function private function AlphaCompare(val1,val2) 'Compare val1 and Val1 ' - returns 0 for same ' 1 if val1 is top ' 2 if val2 is top val1 = lcase(trim(val1)) val2 = lcase(trim(val2)) if val1 = val2 then AlphaCompare = 0 exit function end if len1 = len(val1) len2 = len(val2) if len1 < len2 then checkchars = len1 'len1 is shorter so the default '(if everything else the same) is 1 AlphaCompare = 1 else checkchars = len2 'len1 is shorter so the default '(if everything else the same) is 2 AlphaCompare = 2 end if FOR n = 1 to checkchars checkchar1 = asc(mid(val1,n,1)) checkchar2 = asc(mid(val2,n,1)) if checkchar1 < checkchar2 then AlphaCompare = 1 exit function end if if checkchar2 < checkchar1 then AlphaCompare = 2 exit function end if next end function End Class %>