# Multi-Dimensional Arrays

Since elements of an array may be any data type, may be also an array. And when any element of an array is an array, it called multi-dimensional array.

As cited in array-basics, multi-dimensional array too subscripted like single dimension array. Only difference is specifying separate subscript for each dimension. This is correct for both defining and retrieving.

For example:

`aArray2D := ARRAY( 2, 3 )`
`? HB_ValToExp( aArray2D )  // {{NIL, NIL, NIL}, {NIL, NIL, NIL}}`
`aArray2D := { { 1, 2, 3 }, { 4, 5, 6 } }`
`? HB_ValToExp( aArray2D )  // {{1, 2, 3}, {4, 5, 6}}`

A multi-dim array doesn’t have to be “uniform”; any element of an array may be an array :

`aArrMDim := { 1, "One", DATE(), .T., { 1, 2, 3, 4 } }`
`? HB_ValToExp(aArrMDim )  // {1, "One", 0d20130108, .T., {1, 2, 3, 4}}`

In such case we can’t talk about aArrMDim[ 1, 1 ], aArrMDim[ 3, 2 ], … only aArrMDim[ 5, 1 ], aArrMDim[ 5, 2 ], …

Since fifth element of aArrMDim is a array, we can any array operation on it:

`ASIZE( aArrMDim[ 5 ], 2 )`
`? HB_ValToExp(aArrMDim[ 5 ] )  // {1, 2}`
`? LEN( aArrMDim[ 5 ] )         // 2`

Language doesn’t enforce any rules on what can be stored in an array; this level of control must be implemented programmatically.

The fact that you can assign an array ( or any data type else ) to an existing array element allows you to dynamically change structure of an array. For example, after an array built there is nothing prevent you from doing something like this:

`aArrMDim[ 2 ] := { 2.5, 5.75, 3.14 }`

This statement change second element of array from string to array. Now, aArrMDim[ 2, 3 ], aArrMDim[ 5, 3 ] are valid, but aArrMDim[ 3, 1 ] result a runtime error.

This feature of assigning an array reference to an array element can come in handy in lot of applications. The thing to remember is that you as the programmer must exercise whatever control you think is necessary for storing and addressing array elements. You cannot make any assumption about the structure of an array unless you enforce that structure.

`PROCEDURE Main()`
`   ?`
`   ? "Multi-dim arrays :"`
`   ?`

`   aArray2D := ARRAY( 2, 3 )`
`   ShowValue( aArray2D, "two-dim"  )`
`   Show2DArr( aArray2D )`

`   aArray2D := { { 1, 2, 3 }, { 4, 5, 6 } }`
`   ShowValue( aArray2D, "two-dim"  )`
`   Show2DArr( aArray2D )`

`   aArrMDim := { 1, "One", DATE(), .T., { 1, 2, 3, 4 } }`
`   ShowValue( aArrMDim, "Multi-dim"  )`

`   ? "Before ASIZE() :", LEN( aArrMDim )`
`   ASIZE( aArrMDim[ 5 ], 2 )`
`   ShowValue( aArrMDim, "Shrinked subarray"  )`
`   ? "After ASIZE() :", LEN( aArrMDim )`
`   ? HB_ValToExp(aArrMDim[ 5 ] )  // {1, 2}`
`   ? LEN( aArrMDim[ 5 ] ) //`
`   ShowValue( aArrMDim, "Shrinked"  )`

`   ?`
`   @ MAXROW(), 0`
`   WAIT "EOF MD_Arrays.prg"`

`RETURN // MD_Arrays.Main`

`*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._`

`PROCEDURE ShowValue( xValue, cComment )`
`   LOCAL cType := VALTYPE( xValue )`
`   ? cComment, ":",;`
`     ValType( xValue ),;`
`     IF( cType \$ "CMA", HB_ValToExp( LEN( xValue ) ),''),;`
`     HB_ValToExp( xValue )`
`   ?`
`RETURN // ShowValue()`
`*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._`
`PROCEDURE Show2DArr( a2DArr )`
`   ?`
`   FOR nD1 := 1 TO 2`
`      FOR nD2 := 1 TO 3`
`         ?? a2DArr[ nD1, nD2 ]`
`      NEXT`
`      ?`
`   NEXT`
`RETURN // Show2DArr()`
`*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._`