How to determine the number of dimensions in an array

  • Thread starter Thread starter Steve
  • Start date Start date
S

Steve

Is there any other (simple) way to determine the number of dimensions an
array has, other than having to iteratively cycle through calls of
UBOUND(myArray,N) until an error arises ?
 
Steve wrote...
Is there any other (simple) way to determine the number of dimensions an
array has, other than having to iteratively cycle through calls of
UBOUND(myArray,N) until an error arises ?

No, which is why it's one of the first things developers write a
function to handle. FWIW, many languages (Pascal, C, FORTRAN) also lack
any way of determining the number of array dimensions at runtime.
Indeed, I can think of only APL and its derivatives and math/stats mini
languages that provide built-in functions to return the number of array
dimensions at runtime.
 
Cool. Then that confirms that I'm not missing something thanks. Now... next
question off this one is, what'd you recommend as being the "best" way of
determining the number of dimensions in any given array passed to a
function.

Regards


Steve
 
Steve wrote...
Cool. Then that confirms that I'm not missing something thanks. Now... next
question off this one is, what'd you recommend as being the "best" way of
determining the number of dimensions in any given array passed to a
function.

The 'best' way is the obvious way, which you already described. This is
what I use.


'Returns the 'rank' of array arguments, otherwise zero. Rank is defined
'as the result from the APL operation rho rho m.
Function arank(x As Variant) As Long
Dim n As Long

If Not IsArray(x) Then Exit Function Else n = 1

On Error Resume Next

Do
n = n + 1
Loop While (LBound(x, n) <= UBound(x, n))

arank = n - 1
End Function
 
Harlan said:
Steve wrote...



The 'best' way is the obvious way, which you already described. This is
what I use.


'Returns the 'rank' of array arguments, otherwise zero. Rank is defined
'as the result from the APL operation rho rho m.
Function arank(x As Variant) As Long
Dim n As Long

If Not IsArray(x) Then Exit Function Else n = 1

On Error Resume Next

Do
n = n + 1
Loop While (LBound(x, n) <= UBound(x, n))

arank = n - 1
End Function

Slightly more robust:

Function arank2(x As Variant) As Variant
Dim n As Long

If Not IsArray(x) Or TypeOf x Is Range Then
arank2 = "Not an array."
Exit Function
Else
n = 1
End If

On Error Resume Next

Do
n = n + 1
Loop While (LBound(x, n) <= UBound(x, n))

arank2 = n - 1
End Function

Alan Beban
 
Just the way I've done it (adding Alan's TypeOf check):

Public Function NumberOfDimensions(vArr As Variant) As Long
Const MAXDIMENSIONS As Long = 60
Dim i As Long
If IsArray(vArr) And Not TypeOf vArr Is Range Then
On Error GoTo Done
For i = 2 To MAXDIMENSIONS
IsNumeric LBound(vArr, i)
Next i
Done:
NumberOfDimensions = i - 1
End If
End Function
 
Alan Beban wrote...
....
Slightly more robust:

Function arank2(x As Variant) As Variant
Dim n As Long

If Not IsArray(x) Or TypeOf x Is Range Then
arank2 = "Not an array."
Exit Function
....

Why limit the TypeOf check just to Range objects? If MAX ROBUSTNESS is
the goal, then it'd make more sense to make the condition


If Not IsArray(x) Or IsObject(x) Then Exit Function Else n = 1


Also, you consistently fail to comprehend the reason for returning an
integer from a function like this under ALL circumstances. Making the
function return a variant that could possibly be a string *REQUIRES*
that the calling procedure assign the return value to a Variant type
variable, which eats more memory. Also, when checking the result,

result > 0

is a much easier, much quicker, much less memory intensive test than

IsNumeric(result)

So, other than your peculiar aesthetics, do you have any good reason
for returning a string rather than 0?
 
The foll. works just fine for me. The dimension of any variable that is
not usable as an array is 0.

Option Explicit

Function NbrDimensions(x As Variant) As Byte
Dim i As Byte, n As Long
i = 1
On Error GoTo ErrXIT
Do While True
n = LBound(x, i)
i = i + 1
Loop
ErrXIT:
NbrDimensions = i - 1
End Function
Sub testIt()
Dim i As Integer, s As String, r As Range, _
x(1 To 10) As Long, y, z()
MsgBox NbrDimensions(i) & "," & NbrDimensions(s) & "," _
& NbrDimensions(r) & "," _
& NbrDimensions(x) & "," & NbrDimensions(y) & "," _
& NbrDimensions(z)
Set r = Range("a1:B10")
ReDim y(1 To 10, 1 To 10)
ReDim z(-10 To -1, 0 To 0, 100 To 102)
MsgBox NbrDimensions(i) & "," & NbrDimensions(s) & "," _
& NbrDimensions(r) & "," _
& NbrDimensions(x) & "," & NbrDimensions(y) & "," _
& NbrDimensions(z)
End Sub

If you must distinguish between an unitialized dynamic array and a non-
array, use

Function NbrDimensions(x As Variant) As Integer
Dim i As Byte, n As Long
If Not IsArray(x) Or TypeName(x) = "Range" Then _
NbrDimensions = -1: Exit Function
i = 1
On Error GoTo ErrXIT
Do While True
n = LBound(x, i)
i = i + 1
Loop
ErrXIT:
NbrDimensions = i - 1
End Function

--
Regards,

Tushar Mehta
www.tushar-mehta.com
Multi-disciplinary business expertise
+ Technology skills
= Optimal solution to your business problem
Recipient Microsoft MVP award 2000-2005
 
Harlan said:
Steve wrote... dimensions

No, which is why it's one of the first things developers write a
function to handle. FWIW, many languages (Pascal, C, FORTRAN) also lack
any way of determining the number of array dimensions at runtime.

In all versions of Fortran so far, the number of array dimensions is
known at compile time. Since Fortran 90, the array bounds can be
queried at run-time using the SIZE function.
 
(e-mail address removed) wrote...
....
In all versions of Fortran so far, the number of array dimensions is
known at compile time. Since Fortran 90, the array bounds can be
queried at run-time using the SIZE function.

Shoulda known F90 differed from F77.
 
Back
Top