Rhinoscript:one dimensional arrays
From ksteinfeWiki
Contents |
Overview
Let's say you need your script to remember a series of numbers. You know how to create and use variables at this point - you could just make a new variable for each number you want to remember, like this:
Dim dblN1, dblN2, dblN3, dblN4, dblN5
dblN1 = 6.0
dblN2 = 6.2
dblN3 = 6.4
dblN4 = 6.8
dblN5 = 7.0
Now, if you wanted to print out the number 6.6 to the console, you could do so like this:
Rhino.Print(dblN4)
And if you wanted to print all your numbers to the console, you could do this:
Rhino.Print(dblN1)
Rhino.Print(dblN2)
Rhino.Print(dblN3)
Rhino.Print(dblN4)
Rhino.Print(dblN5)
This works fine for a limited and fixed number of variables, but a problem arises if you want to keep track of a large number of variables - what if you wanted to remember 100 numbers? 1000? If you were to try to manually declare and define each of these, you would have quite a task on your hands. Also, what do you do if you're not sure how many variables you wish to store? For example, if you allow the user to pick any number of objects to work on... how can you know in advance how many variables to create?
In each of these situations, using an array is required. An array is simply a list of variables packaged together. It's like a carton full of variables. Using an array for the situation pictured above, we might end up with something like this:
ReDim arrNumbers(9)
arrNumbers(0) = 6.2
arrNumbers(1) = 6.4
arrNumbers(2) = 6.6
arrNumbers(3) = 6.8
arrNumbers(4) = 7.0
arrNumbers(5) = 7.2
arrNumbers(6) = 7.4
arrNumbers(7) = 7.6
arrNumbers(8) = 7.8
arrNumbers(9) = 8.0
At first wash, this doesn't seem like too much less work... we still have one line of code for every number we want to remember, right? Well, let's look at what happens when we print this same information to the console. Retrieving the number 6.6 works in much the same way:
Rhino.Print(arrNumbers(2))
// prints '6.6' to the console
But, when we want to print all the numbers we've stored to the console, we may now use a For Loop. In the example below, we use a the vb function UBound(), a full discussion of which is to follow. For now, just know that this function returns the number of items in the array.
For i = 0 To UBound(arrNumbers)
Call Rhino.Print("item "&(i)&" is equal to " & arrNumbers(i))
Next
Declaration, Assignment, and Retrieval
1d Array Declaration
Declaring an array is just like declaring any other variable, with two exceptions: the use of the ReDim keyword, and the use of parenthesis after the name assignment.
ReDim arrNumbers(9)
With this line of code, a new array is declared and given a name, in this case "arrNumbers". The number in parenthesis indicates how many placeholders are contained within it, and in this case we initiate slots 0-9. It's important to note that because these placeholders are numbered started at 0, there are actually TEN places to hold information here.
Just like variable declaration, items in an array are empty until you fill them up with something. This can be surprisingly tricky business, and it's important to keep track of how many items your array can hold, and how much its holding at any given moment.
ReDim
You may have noticed in the example above the use of the new keyword ReDim in the place of Dim. While the difference between these two keywords is more nuanced, for our purposes you should always use the keyword ReDim when declaring an array.
Always!
(one exception, noted below)
1d Array Assignment
You may assign data to an array just the same way you do to a variable, except you have to provide an additional piece of information - where in the array to place it. In the example above, we did this in order, filling up the array slots moving from 0->9. This isn't the only way to go about it, the example below works just fine, although the first doesn't completely fill up the array.
ReDim arrNumbers(9)
arrNumbers(5) = 7.2
arrNumbers(6) = 7.4
arrNumbers(2) = 6.6
arrNumbers(8) = 7.8
After running just these lines of code, we would have an array which is not completely populated. If we were to ask rhino for the number in, say slot four of this array (arrNumbers(4)), we would end up with nothing... a potential problem.
A better way to populate your arrays is by using a for loop . The code shown below will result in a fully populated array.
Dim i
For i = 0 To 9
arrNumbers(i) = 6.2+(i*.2)
Next
If you attempt to assign a value to an array at an index which doesn't exist, you'll get an error.
[ERROR] "Subscript out of range 10"
arrNumbers(10) = 10.0
[ERROR] "Subscript out of range i"
Dim i
For i = 0 To 10
arrNumbers(i) = 6.2+(i*.2)
Next
[ERROR] "Subscript out of range -2"
arrNumbers(-2) = 10.0
1d Array Quick Syntax
There's a special syntax for quickly declaring and assigning all elements of an array at the same time. This shorter syntax is handy for times when you've already got all the elements you need at hand or for very small arrays. For example, when defining three numbers to be used as coordinates to plot a point you could use the longhand we've learned:
ReDim arrPoint(2)
arrPoint(0) = 3.0
arrPoint(1) = 2.5
arrPoint(2) = 0.0
Or, you could use the shorthand below. Notice how in this special case (and only in this special case), we use a Dim statement rather than a ReDim statement to declare the array. Also note the use of the Array keyword.
Dim arrPoint
arrPoint = Array( 3.0 , 2.5 , 0.0 )
1d Array Retrieval
Retrieving data from an array works just like you might expect by now - exactly the way a variable works, with the addition of an index to indicate which item you're after.
Dim x
x = arrNumbers(5)
'' x is now equal to 7.2
x = arrNumbers(0)
'' x is now equal to 6.2
Rhino.Print( arrNumbers(1) )
''prints 6.4 to the console
If you attempt to retrieve a value from an array at an index which doesn't exist, you'll also get an error.
[ERROR] "Subscript out of range 10"
x = arrNumbers(10)
[ERROR] "Subscript out of range i"
Dim i
For i = 0 To 10
Rhino.Print(arrNumbers(i))
Next
[ERROR] "Subscript out of range -2"
x = arrNumbers(-2)
UBound in 1d Arrays
UBound is short for "Upper bound", which is the terminology used to indicate the highest possible index of an array. Notice that this does not indicate the total number slots in the array (remember, we start counting at 0), nor does it indicate how many slots in the array are actually filled.
The UBound function is extremely useful for iterating through arrays, as we have seen above.
arrNumbers(9)
Rhino.Print( UBound(arrNumbers) )
''prints '9' to the console
Dim i
For i = 0 To UBound(arrNumbers)
arrNumbers(i) = 6.2+(i*.2)
Next
''completely fills up the arrNumbers array
If we attempt to use the UBound() function on an array which cannot contain any elements, there will be a fatal error
arrNumbers()
Rhino.Print( UBound(arrNumbers) )
[ERROR]
Resizing 1d Arrays
Sometimes in a script, there is no way to anticipate how many items you will need to store in advance. For example, you ask the user to select any number of objects on which to perform an operation. Or, you find the intersection between a line and a circle, and wish to store the points for later use (there may be as few as zero and as many as two in this case). For both of these situations, you'll need to be able to change the size of an array which you've already defined. Let's take a look at how to do this.
Let's say that we'd like to resize the array we've been working with above. As a refresher, here's what we had:
ReDim arrNumbers(9)
Dim i
For i = 0 To 10
arrNumbers(i) = 6.2+(i*.2)
Next
Now, let's say we'd like eleven available slots, rather than ten (remember, the upper bound index (UBound) is one less than the total number of slots. It seems a logical step to try to ReDim the array again, as seen below.
ReDim arrNumbers(10)
As you can see above, simply ReDim'ing the array again does indeed give us our extra slot, but it erases the data which used to reside in the array as well. Good to know, but not exactly what we wanted. We wanted to add data to the array - keeping the data that we already had, and simply increasing the carrying capacity of the array. This is the function of the Preserve keyword. Check out the code and related diagram below.
ReDim Preserve arrNumbers(10)
