Multi-dimensional array: Difference between revisions

m
m (→‎{{header|Phix}}: added syntax colouring the hard way, phix/basics)
m (→‎{{header|Wren}}: Minor tidy)
 
(17 intermediate revisions by 13 users not shown)
Line 1:
{{task}}
{{omit from|PicoLisp}}
For the purposes of this task, the actual memory layout or access method of this data structure is not mandated. It is enough to:
For the purposes of this task, the actual memory layout or access method of this data structure is not mandated.
 
It is enough to:
# State the number and extent of each index to the array.
# Provide specific, ordered, integer indices for all dimensions of the array together with a new value to update the indexed value.
# Provide specific, ordered, numeric indices for all dimensions of the array to obtain the arrays value at that indexed position.
 
 
;The task is to:
;Task:
* State if the language supports multi-dimensional arrays in its syntax and usual implementation.
* State whether the language uses [https://en.wikipedia.org/wiki/Row-major_order row-major or column major order] for multi-dimensional array storage, or any other relevant kind of storage.
Line 12 ⟶ 16:
* State if memory allocation is optimised for the array - especially if contiguous memory is likely to be allocated.
* If the language has exceptional native multi-dimensional array support such as optional bounds checking, reshaping, or being able to state both the lower and upper bounds of index ranges, then this is the task to mention them.
 
 
Show all output here, (but you may judiciously use ellipses to shorten repetitive output text).
<br><br>
{{omit from|PicoLisp}}
 
=={{header|11l}}==
11l doesn’t provided multidimensional arrays. When needed, they can be simulated as arrays of arrays, arrays of arrays of arrays and so on.
<syntaxhighlight lang="11l">V arr = [
[
[1,2,3],
[4,5,6]
],
[
[11,22,33],
[44,55,66]
],
[
[111,222,333],
[444,555,666]
],
[
[1111,2222,3333],
[4444,5555,6666]
]
]</syntaxhighlight>
 
=={{header|Ada}}==
Line 24 ⟶ 50:
 
Ada array indices employ the concept of a range. A range is specified as Low_Value .. High_Value. The range is inclusive of both the low value and the high value.
<syntaxhighlight lang="ada">
<lang Ada>
type Grade is range 0..100;
subtype Lower_Case is Character range 'a'..'z';
Line 30 ⟶ 56:
subtype Positive is Integer range 1..Integer'Last;
type Deflection is range -180..180;
</syntaxhighlight>
</lang>
Grade is defined as a distinct integer type with valid values from 0 through 100.
Line 45 ⟶ 71:
Ada array types may be constrained types or unconstrained types. A constrained type is defined with a constrained index range. An unconstrained type is defined with an unconstrained index range. All instances of an unconstrained array type are themselves constrained.
{{Single dimensional arrays}}
<syntaxhighlight lang="ada">
<lang Ada>
type Char_Array is array (0..9) of Character; -- A constrained array of characters
type String is array (Positive range <>) of Character; -- An unconstrained array of characters
</syntaxhighlight>
</lang>
All instances of Char_Array as defined above have a length of 10 characters with a lower index bound of 0 and an upper index bound of 9. The definition of the type String above is the standard Ada definition for a fixed length string type. Within the index definition we see "Positive range <>". This indicates that an instance of type String must have an index range within the valid range for the pre-defined integer subtype named Positive. Positive is defined as all integer values beginning at 1 and continuing to the highest integer value. The definition of Positive is
<syntaxhighlight lang="ada">
<lang Ada>
subtype Positive is Integer range 1..Integer'Last;
</syntaxhighlight>
</lang>
String literals are indexed beginning at index value 1.
<syntaxhighlight lang="ada">
<lang Ada>
Name : String := "Rosetta Code";
</syntaxhighlight>
</lang>
The instance of string identified as Name above is created and initialized to hold the value "Rosetta Code". The first index value for Name is 1. The last index value for Name is 12.
 
Line 64 ⟶ 90:
 
''''Length''' This attribute returns the number of array elements of a single-dimensional array.
<syntaxhighlight lang="ada">
<lang Ada>
Num_Elements : Natural := Char_Array'Length;
</syntaxhighlight>
</lang>
 
''''Length(N)''' This attribute returns the number of elements for the Nth of an array.
Line 87 ⟶ 113:
 
Ada allows the definition of an array type which is any array of another array type.
<syntaxhighlight lang="ada">
<lang Ada>
type Vector is array (1..10) of Integer;
type Table is array (0..99) of Vector;
</syntaxhighlight>
</lang>
In this example, one can access the second element of an instance of type Vector using the notation
<syntaxhighlight lang="ada">
<lang Ada>
V : Vector;
...
V(2) := 10;
</syntaxhighlight>
</lang>
Accessing the second element of the vector on the second row of Table is done as
<syntaxhighlight lang="ada">
<lang Ada>
T : Table;
...
T(1)(2) := 10;
</syntaxhighlight>
</lang>
Each element of Table is an instance of Vector. Each element of Vector is an Integer.
 
Line 108 ⟶ 134:
 
Ada also allows the definition of multi-dimensional arrays.
<syntaxhighlight lang="ada">
<lang Ada>
type Matrix is array (0..99, 1..10) of Integer;
M : Matrix;
...
M(1,2) := 10;
</syntaxhighlight>
</lang>
The example above shows how to access the element in the second row and second column of an instance of Matrix.
 
Whole array instances can be assigned to other arrays of the same type.
<syntaxhighlight lang="ada">
<lang Ada>
Mat1 : Matrix;
Mat2 : Matrix;
...
Mat1 := Mat2;
</syntaxhighlight>
</lang>
The above assignment creates a deep copy. After the assignment Mat1 and Mat2 are separate instances of Matrix containing the same values.
 
Slices of arrays can also be assigned to instances of the same array type such as
<syntaxhighlight lang="ada">
<lang Ada>
V1 : Vector := (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
V2 : Vector := (2, 2, 2, 2, 2, 2, 2, 2, 2, 2);
...
V2(3..6) := V1(7..10);
</syntaxhighlight>
</lang>
When assigning whole arrays or slices of arrays the sizes must match, but the index ranges can be different. In the example above each slice contains 4 data elements. The value of V2 after the assignment is (2, 2, 7, 8, 9, 10, 2, 2, 2, 2).
 
Line 137 ⟶ 163:
 
The Ada "for" loop is used to iterate through arrays without danger of index bounds violations
<syntaxhighlight lang="ada">
<lang Ada>
function "*" (Left : Vector; Right : Integer) return Vector is
Result : Vector;
Line 146 ⟶ 172:
return Result;
end "*"
</syntaxhighlight>
</lang>
The function definition above overloads the multiplication operator "*" allowing the multiplication of every element of and instance of Vector by an Integer value. The "for" loop within the function iterates over each value of the range produced using the 'Range attribute. Unlike some languages such as C or C++, no additional parameter specifying the number of elements in the array is passed. This approach works well for constrained array types. A small variation is used for unconstrained array types.
<syntaxhighlight lang="ada">
<lang Ada>
type Unconstrained_Vector is array (Positive range <>) of Integer;
U1 : Unconstrained_Vector := (1,2,3,4,5,6,7,8,9,10);
Line 161 ⟶ 187:
return Result;
end "*";
</syntaxhighlight>
</lang>
The instance of Unconstrained_Vector defined within the function is initialized to have the same index values as the formal parameter named Left. This version of the function allows the programmer to pass any instance of Unconstrained_Vector to the function "*". In the example above one may pass both U1 and U2 to the function without experiencing index boundary violation.
 
Line 174 ⟶ 200:
The upper and lower bounds are separated by ":" and each pair of bounds is separated from the next by a ",".
The array required by the task could be declared as follows: #
<langsyntaxhighlight lang="algol68">[ 1 : 5, 1 : 4, 1 : 3, 1 : 2 ]INT a;</langsyntaxhighlight>
As the lower bounds are all 1, this could be abbreviated to:
<langsyntaxhighlight lang="algol68">[ 5, 4, 3, 2 ]INT a;</langsyntaxhighlight>
Note that the lower and upper bounds can be 0 or negative, e.g. the following declares an array of the same size but different bounds:
<langsyntaxhighlight lang="algol68">[ -7 : -3. -3 : 0, -1 : 1, 0 : 1 ]INT x;</langsyntaxhighlight>
Individual array elements can be set and accessed by stating the index values separated by ",".
The following sets the lowest element of the array to 0:
<langsyntaxhighlight lang="algol68">a[ 1, 1, 1, 1 ] := 0;</langsyntaxhighlight>
The following sets the highest element to the lowest:
<langsyntaxhighlight lang="algol68">a[ 5, 4, 3, 2 ] := a[ 1, 1, 1, 1 ];</langsyntaxhighlight>
Subsets of the array can be set and accessed by stating the index values of the subsets,
e.g. the following sets a pair of elements near the start of the array to a pair of elements near the end:
Selecting a subset of an array is known as slicing.
<langsyntaxhighlight lang="algol68">a[ 3 : 4, 1, 1, 1 ] := a[ 5, 4, 2 : 3, 1 ];</langsyntaxhighlight>
The whole array can also be assigned, e.g., the following sets the entire array to some values, using nested "literal arrays" (known as row-displays):
<langsyntaxhighlight lang="algol68"># Note this requires the lower bounds of each index be 1 #
a := ( ( ( ( 1111, 1112 ), ( 1121, 1122 ), ( 1131, 1132 ) )
, ( ( 1211, 1212 ), ( 1221, 1222 ), ( 1231, 1232 ) )
Line 209 ⟶ 235:
, ( ( 5211, 5212 ), ( 5221, 5222 ), ( 5231, 5232 ) )
, ( ( 5311, 5312 ), ( 5321, 5322 ), ( 5331, 5332 ) )
, ( ( 5411, 5412 ), ( 5421, 5422 ), ( 5431, 5432 ) ) ) );</langsyntaxhighlight>
If the lower bounds are not 1, they can be temporarily be changed to 1 by using the "AT" construct, e.g. as in the following:
 
<langsyntaxhighlight lang="algol68"># declare an array the same size as a, but with all lower bounds equal to 2: #
[ 2 : 6, 2 : 5, 2 : 4, 2 : 3 ]INT b;
 
Line 236 ⟶ 262:
, ( ( 5211, 5212 ), ( 5221, 5222 ), ( 5231, 5232 ) )
, ( ( 5311, 5312 ), ( 5321, 5322 ), ( 5331, 5332 ) )
, ( ( 5411, 5412 ), ( 5421, 5422 ), ( 5431, 5432 ) ) ) );</langsyntaxhighlight>
Bounds checking is standard and there is no standard way to turn it off. There may be implementation-specific mechanisms (probably using pragmatic comments) to do so.
 
Line 248 ⟶ 274:
The bounds of the array can be determined using the LWB and UPB operators.
For a 1 dimensional array, the unary LWB and UPB operators can be used.
<langsyntaxhighlight lang="algol68"># E.g. the following prints the lower and upper bounds of the first two #
# indexes of a ( in this case, 1, 5, 1 and 4 ) #
print( ( 1 LWB a, 1 UPB a, 2 LWB a, 2 UPB a, newline ) );</langsyntaxhighlight>
{{out}}
<pre> +1 +5 +1 +4</pre>
Line 262 ⟶ 288:
The upper and lower bounds are separated by "::" and each pair of bounds is separated from the next by a ",".
The array required by the task could be declared as follows:
<langsyntaxhighlight lang="algolw">integer array a ( 1 :: 5, 1 :: 4, 1 :: 3, 1 :: 2 );</langsyntaxhighlight>
note that the lower and upper bounds can be 0 or negative, e.g. the following declares an array of the same size but different bounds:
<langsyntaxhighlight lang="algolw">integer array x ( -7 :: -3. -3 :: 0, -1 :: 1, 0 :: 1 );</langsyntaxhighlight>
 
individual array elements can be set and accessed by stating the index
values separated by ",". The following sets the lowest element of the array to 0:
<langsyntaxhighlight lang="algolw">a( 1, 1, 1, 1 ) := 0;</langsyntaxhighlight>
 
The following sets the highest element to the lowest:
<langsyntaxhighlight lang="algolw">a( 5, 4, 3, 2 ) := a( 1, 1, 1, 1 );</langsyntaxhighlight>
 
Subsets of an array can be specified as parameters to procedures.
E.g.:
<langsyntaxhighlight lang="algolw">% declare a procedure that has a three-dimensional array parameter %
procedure p ( integer array a1 ( *, *, * ) ) ; a1( 1, 2, 1 ) := 3 ;
 
% call the procedure with a subset of the 4 dimensional array %
p( a( *, 2, *, * ) );</langsyntaxhighlight>
 
The elements of the array can only be set individually, it is not possible to assign
Line 291 ⟶ 317:
=={{header|C}}==
C supports multi-dimensional arrays, and thanks to the inter-op of arrays and points in C, it is possible to target any section of memory and drill down to the bit level. C uses row-major order for storing arrays. There are many ways to declare arrays, or pointers which can then be used as arrays, as shown below :
<langsyntaxhighlight Clang="c">/*Single dimensional array of integers*/
int a[10];
 
Line 327 ⟶ 353:
/*you get the idea*/
 
char **j[][5];</langsyntaxhighlight>
When arrays are declared with all dimensions at the outset, all memory is allocated immediately once the program execution reaches the point where the array is declared. The following implementation shows just a few of the many ways of dealing with arrays :
<syntaxhighlight lang="c">
<lang C>
#include<stdio.h>
 
Line 357 ⟶ 383:
return 0;
}
</syntaxhighlight>
</lang>
Output :
<pre>
Line 366 ⟶ 392:
</pre>
Declared as above or by using the functions malloc or calloc of the C Standard Library, memory is allocated contiguously. This obviously assumes that the machine has sufficient memory. The following implementation shows how a multi pointer can work as an array :
<syntaxhighlight lang="c">
<lang C>
 
#include<stdlib.h>
Line 433 ⟶ 459:
return 0;
}</langsyntaxhighlight>
Output :
<pre>
Line 447 ⟶ 473:
C# supports both multidimensional arrays and jagged arrays (e.g. arrays of arrays).<br/>
A multidimensional array with 2 rows and 3 columns can be initialized with:
<langsyntaxhighlight lang="csharp">var array = new int[,] { //Dimensions are inferred
{ 1, 2, 3 },
{ 4, 5, 6}
Line 455 ⟶ 481:
 
//To create a 4-dimensional array with all zeroes:
var array = new int[5, 4, 3, 2];</langsyntaxhighlight>
Under the hood, this is just one object; one contiguous block of memory is allocated.<br/>
 
For jagged arrays, each dimension must be initialized separately. They can be non-rectangular.
<langsyntaxhighlight lang="csharp">var array = new int[][] { //Dimensions are inferred
new [] { 1, 2, 3, 4 },
new [] { 5, 6, 7, 8, 9, 10 }
Line 476 ⟶ 502:
}
}
}</langsyntaxhighlight>
 
C# also supports arrays with non-zero bounds (mainly for handling arrays that are returned from unmanaged code)
<langsyntaxhighlight lang="csharp">var array = (int[,,,])Array.CreateInstance(typeof(int), new [] { 5, 4, 3, 2 }, new [] { 10, 10, 10, 10 });
int n = 1;
//Note: GetUpperBound is inclusive
Line 495 ⟶ 521:
//The multidimensional array does not implement the generic IEnumerable<int>
//so we need to cast the elements.
Console.WriteLine(string.Join(" ", array.Cast<int>().Take(30)) + " ...");</langsyntaxhighlight>
{{out}}
<pre>
Line 504 ⟶ 530:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <vector>
 
Line 572 ⟶ 598:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>[[[[0, 1, 2, 3]], [[4, 5, 6, 7], [8, 9, 10, 11]]], [[[12, 13, 14, 15]]]]</pre>
 
=={{header|D}}==
<langsyntaxhighlight Dlang="d">import std.stdio;
 
/*
Line 737 ⟶ 763:
nativeExample();
customArray();
}</langsyntaxhighlight>
{{out}}
<pre>Static array: [1, 2, 3]
Line 759 ⟶ 785:
[5, 4, 4]
[5, 5, 5]]</pre>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|}}
 
 
<syntaxhighlight lang="Delphi">
{1. Delphi support arrays of any number of dimensions, including non-orthogonal arrays.}
{2. Delphi arrays are Row Major.}
{3. This creates a five dimensional array in Delphi.}
 
var MyArray: array [0..5,0..4,0..3,0..2] of integer;
 
{4. This reads and writes array items:}
 
MyArray[5,4,3,2]:=MyArray[1,2,3,2];
 
{5. Array memory space can be compacted to guarantee that all items are contiguous.}
 
var MyArray3: packed array [0..5,0..4,0..3,0..2] of integer;
 
{6. You can create array that start at indices other than zero.}
 
var MyArray2: array [5..25,26..50] of integer;
 
{7. You can create non-orthogonal arrays:}
 
var A : array of array of string;
var I, J : Integer;
begin
SetLength(A, 10);
for I := Low(A) to High(A) do
begin
SetLength(A[I], I);
for J := Low(A[I]) to High(A[I]) do
A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
end;
end;
 
</syntaxhighlight>
{{out}}
<pre>
 
</pre>
 
 
=={{header|EchoLisp}}==
EchoLisp natively supports 1 and 2-dimensions arrays : lib '''matrix'''. The following shows an implementation of multi-dimensional arrays, using contiguous memory and bound checking. Indices are vectors #(i j k ...) of integers.
<langsyntaxhighlight lang="scheme">(require 'math) ;; dot-product
 
;; dims = vector #(d1 d2 .....)
Line 806 ⟶ 877:
(define (m-array-set! ma indices value )
(m-array-check ma indices)
(vector-set! ma (m-array-index ma indices) value))</langsyntaxhighlight>
{{out}}
<pre>(define MA (make-m-array #(5 4 3 2) 1))
Line 823 ⟶ 894:
Factor supports multi-dimensional arrays via the <code>arrays.shaped</code> vocabulary. Factor has no widespread syntax for array indexing, so support is provided in the form of words. Both row-major and column-major indexing are available. The underlying data structure of a <code>shaped-array</code> is a flat, contiguous array. <code>arrays.shaped</code> provides an optional word for bounds-checking, <code>shaped-bounds-check</code>, and a word to reshape an array, <code>reshape</code>.
{{works with|Factor|0.99 2020-10-27+}}
<langsyntaxhighlight lang="factor">USING: accessors arrays.shaped io kernel prettyprint sequences ;
 
! Create a 4-dimensional array with increasing elements.
Line 841 ⟶ 912:
! Reshape and show the array.
"Reshaped: " print
{ 5 4 3 2 } reshape .</langsyntaxhighlight>
{{out}}
<pre>
Line 916 ⟶ 987:
}
}
</pre>
=={{header|Forth}}==
Many Forths include words which can be used to generate 1d arrays <code> CARRAY </code> for arrays of one byte and <code> ARRAY </code> for arrays of integers. There's no standard way to create
and use arrays of more than one dimension.
 
The code below is for a word that creates a generalised n-d array. It will often be more practical to create specific array types for any n darrays with their types where they are required.
 
The word <code> darray </code> can be used as follows
 
<syntaxhighlight lang="forth">
4 5 6 7 8 CELL 5 darray test5d \ Creates the array
i j k l m test5d \ Returns the address of test5d[ i, j, k, l, m ]
 
100 i j k l m test5d ! \ Sets contents of test5d[ i, j, k, l, m ] to 100
i j k l m test5d @ \ Gets contents of test5d[ i, j, k, l, m ]
</syntaxhighlight>
 
Tested on Gforth and VFX Forth - both 64 bit Linux.
 
<syntaxhighlight lang="forth">
\ Values used to avoid locals or some confusing stack juggling.
\ They could be replaced by locals if preferred.
0 VALUE addr
0 VALUE ndims
: darray \ Create: d(n-1) .. d0 size n "<name-of-array>" -- ;
\ Does: ix[n-1] .. ix0 -- addr
\ Creates an n dimensional array with axes dn-1 .. d0
 
\ d(n-i) .. d0 - the length of the n dimensions.
\ size - The size in bytes of the basic elenment in the array.
\ - e.g 1 for chars, 2 for 16 bit etc..
\ n - The number of dimensions
 
\ Term stride is taken from numpy. It's the gap between consqutive indices
\ in a given dimension. ix * stride gives an offset from a base address.
 
\ CELLS 0 1 2 ... n+1 n+2 ->
\ Stride[0] addr Stride[n] addr stride[0] stride[n-1] data ->
\ CELL[2] CELL[n+2] size
\ Storing the stride addresses at CELLS 0 and 1 gives fast access for
\ the do loop in the DOES> section to loop through the strides.
 
CREATE
IS ndims HERE IS addr \ n to ndims, HERE to addr
0 , 0 , \ Placeholders for loop-bounds
DUP , \ size stored at CELL[2]
ndims 1- 0 ?DO * DUP , LOOP \ Calculate and store strides 1 to n-1.
HERE addr CELL + ! \ Store high address for strides
* ALLOT \ Calculate and allocate the space
addr 2 CELLS + addr ! \ Calculate & store low addr for strides
 
DOES> \ ix[n-1] .. ix[0] -- addr ;
2@ OVER SWAP ( data-addr stride-addr[n] stride-addr[0] )
?DO
SWAP i @ * + \ multiply strides by indices and add to base address
CELL +LOOP ;
 
2 3 4 5 CELL 4 darray test4d \ 4d array of integers
\ 2 3 4 5 20 4 darray 20byte-records-4D
 
\ Word to fill the array
: test4d-fill
2 0 DO i
3 0 DO i
4 0 DO
5 0 DO
2DUP 100 * SWAP 1000 * +
j 10 * + i +
2 PICK 2 PICK j i test4d !
LOOP
LOOP
DROP LOOP
DROP LOOP ;
 
: [. ." [ " ;
: ]. ." ] " ;
 
defer p-array
: print-4d \ <array-name> -- ; Prints 4d array
' IS p-array
2 0 DO i CR [.
3 0 DO i CR 2 SPACES [.
4 0 DO
CR 4 SPACES [.
5 0 DO
2DUP j i p-array @ 8 .r
LOOP ].
LOOP ].
DROP LOOP ].
DROP LOOP ;
 
test4d-fill
 
print-4d test4d
</syntaxhighlight>
<pre>
[
[
[ 0 1 2 3 4]
[ 10 11 12 13 14]
[ 20 21 22 23 24]
[ 30 31 32 33 34] ]
[
[ 100 101 102 103 104]
[ 110 111 112 113 114]
[ 120 121 122 123 124]
[ 130 131 132 133 134] ]
[
[ 200 201 202 203 204]
[ 210 211 212 213 214]
[ 220 221 222 223 224]
[ 230 231 232 233 234] ] ]
[
[
[ 1000 1001 1002 1003 1004]
[ 1010 1011 1012 1013 1014]
[ 1020 1021 1022 1023 1024]
[ 1030 1031 1032 1033 1034] ]
[
[ 1100 1101 1102 1103 1104]
[ 1110 1111 1112 1113 1114]
[ 1120 1121 1122 1123 1124]
[ 1130 1131 1132 1133 1134] ]
[
[ 1200 1201 1202 1203 1204]
[ 1210 1211 1212 1213 1214]
[ 1220 1221 1222 1223 1224]
[ 1230 1231 1232 1233 1234] ] ] ok
</pre>
 
<syntaxhighlight lang="forth">
-4567 1 2 3 3 test4d ! ok
1 2 3 3 test4d @ . -4567 ok
 
print-4d test4d
</syntaxhighlight>
<pre>
[
[
[ 0 1 2 3 4]
[ 10 11 12 13 14]
[ 20 21 22 23 24]
[ 30 31 32 33 34] ]
[
[ 100 101 102 103 104]
[ 110 111 112 113 114]
[ 120 121 122 123 124]
[ 130 131 132 133 134] ]
[
[ 200 201 202 203 204]
[ 210 211 212 213 214]
[ 220 221 222 223 224]
[ 230 231 232 233 234] ] ]
[
[
[ 1000 1001 1002 1003 1004]
[ 1010 1011 1012 1013 1014]
[ 1020 1021 1022 1023 1024]
[ 1030 1031 1032 1033 1034] ]
[
[ 1100 1101 1102 1103 1104]
[ 1110 1111 1112 1113 1114]
[ 1120 1121 1122 1123 1124]
[ 1130 1131 1132 1133 1134] ]
[
[ 1200 1201 1202 1203 1204]
[ 1210 1211 1212 1213 1214]
[ 1220 1221 1222 1223 1224]
[ 1230 1231 1232 -4567 1234] ] ] ok
 
</pre>
 
=={{header|Fortran}}==
Messing with multi-dimensional arrays has been central from the introduction of Fortran in 1954. Array indexing is with positive integers and always starts with one, so the DIMENSION statement merely specifies the upper bound of an index via integer constants and an array may have up to three dimensions. All storage for an array is contiguous. Access to an element of a one-dimensional array A is via <code>A(''integer expression'')</code> and early Fortran allowed only simple expressions, no more than c*v ± b which is to say an integer constant times an integer variable plus (or minus) an integer constant. These restrictions simplified the thorough optimisation done by the first compiler. Later compilers abandoned those optimisations, relaxed the constraints on index expressions and allowed more dimensions.
<langsyntaxhighlight Fortranlang="fortran"> DIMENSION A(5,4,3,2) !Declares a (real) array A of four dimensions, storage permitting.
X = 3*A(2,I,1,K) !Extracts a certain element, multiplies its value by three, result to X.
A(1,2,3,4) = X + 1 !Places a value (the result of the expression X + 1) ... somewhere...</langsyntaxhighlight>
Compilers typically perform no checking on the bounds of array indices, even when values are being written to some address. An immediate crash would be the best result. Array bound checking may be requested as a compiler option in some cases, resulting in larger code files, slower execution, and some bug detection.
 
Line 929 ⟶ 1,170:
As well, array data could be manipulated with array processing statements, rather than always having to prepare DO-loops or similar, in particular <code>A = 0</code> would set all values of array A to zero, whatever its dimensionality. Thus, given an array B(0:2,0:2), a two-dimensional array, <code>B(1:2,1:2) = 6*A(1,3:4,1,1:2) - 7</code> would select certain elements scattered about in A, perform the calculation, and store the results in a part of B. Hopefully, element-by element without using a temporary array. Even more complicated selections can be made via the RESHAPE intrinsic now available.
 
Data are stored in Fortran arrays in "column-major" order, with the result that successive elements are indexed with the ''left''-most subscript varying most rapidly. Thus, given an array <code>DIMENSION A(3,3)</code> the elements are ordered as A(1,1), A(2,1), A(3,1), A(1,2), A(2,2), A(3,2), A(1,3), A(2,3), A(3,3). This doesn't matter when the array is referenced via something like A(''row'',''column''). However, should the array A be written (or read) or initialised via a DATA statement without specification of indices, that is the order of the values. Consider <langsyntaxhighlight Fortranlang="fortran"> INTEGER A(3,3) !An array, regarded as being a matrix.
DATA A/1,2,3, !Some initial values.
2 4,5,6, !Laid out as if a matrix.
Line 942 ⟶ 1,183:
WRITE (6,1) (A(I,J), J = 1,3) !The columns along a row.
END DO !Onto the next row.
END</langsyntaxhighlight>
Output:
<pre> Writing A...
Line 957 ⟶ 1,198:
 
For large arrays when memory is not truly random-access (on-chip memory versus main memory, main memory versus slower disc storage) a calculation that works along a row will be accessing widely-separated elements in storage, perhaps with only one "hit" per virtual memory page before leaping to another, while an equivalent calculation working down a column will enjoy multiple hits per page. The difference can be large enough to promote usages such as swapping the order of the DO-loops for portions of a calculation, or swapping the order of the indices as by writing <code>A(J,I)</code> when it would be more natural to use <code>A(I,J)</code>.
 
=={{header|FreeBASIC}}==
Multidimensional arrays can be declared as well, and are stored in this
definite order: values differing only in the last index are contiguous
(row-major order).
The maximum number of dimensions of a multidimensional array is 8.
 
<syntaxhighlight lang="vbnet">
'' declare a three-dimensional array of single
'' precision floating-point numbers.
Dim array(1 To 2, 6, 3 To 5) As Single
 
'' The first dimension of the declared array
'' has indices from 1 to 2, the second, 0 to 6,
'' and the third, 3 to 5.
</syntaxhighlight>
 
The total number of elements and the total size (in bytes) of a multi-dimensional
array can be directly obtained using Arraylen and Arraysize, respectively.
 
<syntaxhighlight lang="vbnet">
' Take Care while initializing multi-dimensional array
Dim As Integer multidim(1 To 2, 1 To 5) = {{0,0,0,0,0}, {0,0,0,0,0}}
</syntaxhighlight>
 
<syntaxhighlight lang="vbnet">Dim As Integer A(5,4,3,2)
A(3,1,0,1) = 3100
A(3,1,0,1) = A(3,1,0,1)+1
Print A(3,1,0,1)</syntaxhighlight>
{{out}}
<pre>3101</pre>
 
=={{header|Go}}==
Line 962 ⟶ 1,234:
 
The technique shown here defines a multi-dimensional array type. A constructor allocates a single slice as a flattened representation. This will be a single linear memory allocation. Methods access the slice in row-major order.
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,017 ⟶ 1,289:
fmt.Println(m.ele[len(m.ele)-10:])
m.show(4, 3, 2, 1)
}</langsyntaxhighlight>
{{out}}
<pre>m[4 3 2 1] = 0
Line 1,030 ⟶ 1,302:
Perhaps the simplest mechanism to create a multidimensional array is to reshape a smaller dimensioned array with the desired dimensions:
 
<langsyntaxhighlight Jlang="j">A1=:5 4 3 2$0</langsyntaxhighlight>
This creates an array of 120 zeros arranged in contiguous memory.
 
Note that items along the leading dimension of the array being reshaped are repeated as necessary to fill in all the values of the array. Thus, this is equivalent:
<langsyntaxhighlight Jlang="j">A2=:5 4 $ 1 3 2$ 0</langsyntaxhighlight>
Another candidate for the simplest mechanism to create a multidimensional array is to ask for an array of indices with those dimensions:
<langsyntaxhighlight Jlang="j"> i.2 3 4 5
0 1 2 3 4
5 6 7 8 9
Line 1,066 ⟶ 1,338:
105 106 107 108 109
110 111 112 113 114
115 116 117 118 119</langsyntaxhighlight>
 
Note that these indices are not multi-dimensional indices but simple counting numbers. (Internally, values in the array are arranged contiguously and in this index order.) To obtain the corresponding index, you can use J's antibase verb. For example:
 
<langsyntaxhighlight Jlang="j"> 2 3 4 5#:118
1 2 3 3</langsyntaxhighlight>
 
Normally, in J, you operate on "everything at once", which can be challenging if you have not worked in a language (such as sql or any of a variety of others) which encourages that kind of thinking. Nevertheless, here's some introductory "one at a time" operations:
 
Pulling a single value from an array:
<langsyntaxhighlight Jlang="j"> (<1 2 3 3) { i.2 3 4 5
118</langsyntaxhighlight>
Setting a single value in an array:
<langsyntaxhighlight Jlang="j">A3=: 987 (<1 2 3 3)} i. 2 3 4 5</langsyntaxhighlight>
And, to reduce vertical space used in this task, here's an example of extracting a sub-array:
<langsyntaxhighlight Jlang="j"> (<1 2){A3
100 101 102 103 104
105 106 107 108 109
110 111 112 113 114
115 116 117 987 119</langsyntaxhighlight>
 
Note that bounds are checked when indexing from the array, or when combining with another array.
<langsyntaxhighlight Jlang="j"> (<5 5 5 5){A3
|index error</langsyntaxhighlight>
and
<langsyntaxhighlight Jlang="j"> A1+A3
|length error</langsyntaxhighlight>
 
For more introductory material on multi-dimensional arrays, you might be interested in [http://www.jsoftware.com/help/learning/05.htm chapter 5] and [http://www.jsoftware.com/help/learning/07.htm chapter 7] of the Learning J book.
Line 1,099 ⟶ 1,371:
{{trans|Kotlin}}
Same description for limitations of the JVM apply here as is described in the Kotlin implementation of the task.
<langsyntaxhighlight Javalang="java">public class MultiDimensionalArray {
public static void main(String[] args) {
// create a regular 4 dimensional array and initialize successive elements to the values 1 to 120
Line 1,128 ⟶ 1,400:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>First element = 1
Line 1,141 ⟶ 1,413:
 
One approach pairs an array of dimensions with an array of values.
<langsyntaxhighlight lang="javascript">function array() {
var dimensions= Array.prototype.slice.call(arguments);
var N=1, rank= dimensions.length;
Line 1,147 ⟶ 1,419:
this.dimensions= dimensions;
this.values= new Array(N);
}</langsyntaxhighlight>
 
A routine to convert between single dimension indices and multi-dimensional indices can be useful here:
 
<langsyntaxhighlight lang="javascript">function tobase(base, vals) {
var r= 0, len= base.length;
for (j= 0; j < len; j++) {
Line 1,167 ⟶ 1,439:
}
return r;
}</langsyntaxhighlight>
For example, array indexing in this approach might be implemented something like:
 
<langsyntaxhighlight lang="javascript">
array.prototype.index= function() {
var indices= Array.prototype.slice.call(arguments);
return this.values[tobase(this.dimensions, indices)];
}
</syntaxhighlight>
</lang>
This would allow things like:
<langsyntaxhighlight lang="javascript">a= new array(6,7,8,9);
a.index(2,3,5,6);</langsyntaxhighlight>
 
But a proper implementation of the index method should include array bounds checking.
Line 1,185 ⟶ 1,457:
 
Another approach "nests" arrays inside other arrays:
<langsyntaxhighlight lang="javascript">
function array(length) {
var rest= Array.prototype.slice.call(arguments);
Line 1,194 ⟶ 1,466:
}
}
}</langsyntaxhighlight>
This approach is superficially simpler but may turn out to be considerably slower.
 
Line 1,233 ⟶ 1,505:
To create a multi-dimensional array with dimensions specified by an
array, d, we can define a recursive function as follows:
<langsyntaxhighlight lang="jq"># The input is used to initialize the elements of the
# multi-dimensional array:
def multiarray(d):
Line 1,239 ⟶ 1,511:
| if (d|length) == 1 then [range(0;d[0]) | $in]
else multiarray(d[1:]) | multiarray( d[0:1] )
end;</langsyntaxhighlight>
A four-dimensional array as specified by the task description can now be created as follows:
Line 1,247 ⟶ 1,519:
For convenience of reference, let us name this array by wrapping it in
a function:
<langsyntaxhighlight lang="jq">def ary: 0 | multiarray( [5, 4, 3, 2] );</langsyntaxhighlight>
 
'''Access and Update'''
To access the [4,3,2,1] element of the previously defined multi-dimensional array, one can either write:
<langsyntaxhighlight lang="jq">ary | .[4][3][2][1]</langsyntaxhighlight>
or
<langsyntaxhighlight lang="jq">ary | getpath( [4,3,2,1])</langsyntaxhighlight>
 
To illustrate, let us define an array of indices:
<langsyntaxhighlight lang="jq">def ix: [4,3,2,1];</langsyntaxhighlight>
 
To check that the two approaches for accessing an element are equivalent:
<langsyntaxhighlight lang="jq">ary | setpath(ix; 100) | getpath(ix)
#=> 100
 
ary | setpath(ix; 100) | .[4][3][2][1]
#=> 100</langsyntaxhighlight>
 
'''Ascertaining the Dimensions of a Multi-dimensional Array'''
Line 1,270 ⟶ 1,542:
regular multi-dimensional array; it returns [] for a scalar, and null
for an irregularly shaped array:
<langsyntaxhighlight lang="jq">def dimensions:
def same(f):
if length == 0 then true
Line 1,282 ⟶ 1,554:
end
else []
end;</langsyntaxhighlight>
 
For exampe:
<langsyntaxhighlight lang="jq">ary | dimensions
#=> [5,4,3,2]</langsyntaxhighlight>
 
=={{header|Julia}}==
Line 1,292 ⟶ 1,564:
<br /><br />
Demonstrated below, from a Julia REPL session, using a random integer four-dimensional array:
<langsyntaxhighlight lang="julia">
julia> a4d = rand(Int, 5, 4, 3, 2)
5×4×3×2 Array{Int64,4}:
Line 1,386 ⟶ 1,658:
julia> a4d[4,3,2,1]
2213007499408257641
</syntaxhighlight>
</lang>
 
=={{header|Klingphix}}==
<langsyntaxhighlight Klingphixlang="klingphix">include ..\Utilitys.tlhy
 
0 ( 4 3 2 ) dim pstack
Line 1,408 ⟶ 1,680:
pstack
 
"End " input</langsyntaxhighlight>
 
=={{header|Kotlin}}==
Line 1,416 ⟶ 1,688:
 
Arrays in Kotlin always start from an index of zero and, in the version which targets the JVM, bounds are checked automatically.
<langsyntaxhighlight lang="scala">// version 1.1.2
 
fun main(args: Array<String>) {
Line 1,441 ⟶ 1,713:
print(f.format(a4[i][j][k][l]))
 
}</langsyntaxhighlight>
{{out}}
<pre>First element = 1
Line 1,450 ⟶ 1,722:
Lingo has no special multi-dimensional array support, but such arrays can be implemented based on nested lists.<br />
(Note: code partially stolen from Lua solution).
<langsyntaxhighlight Lingolang="lingo">on array ()
cnt = paramCount()
if cnt=0 then return
Line 1,463 ⟶ 1,735:
end repeat
return arr
end</langsyntaxhighlight>
 
<langsyntaxhighlight Lingolang="lingo">-- creates 4-dimensional array with specified ranges (data defaults to 0)
a = array(2, 3, 4, 5)
put a[1][2][3][4]
Line 1,474 ⟶ 1,746:
a[1][2][3][4] = 42
put a[1][2][3][4]
-- 42</langsyntaxhighlight>
 
=={{header|Lua}}==
Lua does not support straightforward declaration of multidimensional arrrays but they can be created in the form of nested tables. Once such a structure has been created, elements can be read and written in a manner that will be familiar to users of C-like languages.
<langsyntaxhighlight Lualang="lua">-- Variadic, first argument is the value with which to populate the array.
function multiArray (initVal, ...)
local function copy (t)
Line 1,519 ⟶ 1,791:
show4dArray(t)
t[1][1][1][1] = true
show4dArray(t)</langsyntaxhighlight>
{{out}}
<pre>Printing 4D array in 2D...
Line 1,589 ⟶ 1,861:
4 a a a a a</pre>
This is not memory-efficient and any advanced operations will have to be written if required. A much easier solution is to use an extension module such as densearray available from luarocks.org.
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Mathematica's List can contain other lists, which again can contain lists etc. In this way multi-dimensional array (lists) can be constructed. If all the types are the same, then the multi-dimensional array can be stored as a PackedArray, which stores the array in an efficient manner, it is not clear if this is row or column first. To check if the list is stored as a PackedArray, use the function Developer`PackedArrayQ. If the nested list structure is created manually, then one can convert it to a PackedArray using Developer`ToPackedArray. Elements can be replaced using indices, if the number of indices is smaller than the dimensions, it will not just replace values, but rather, lists, matrices, or multi-dimensional arrays:
<syntaxhighlight lang="mathematica">a = ConstantArray[0, {2, 3, 4, 5}]
a[[1, 2, 3, 4]] = 15;
a[[1, 2, 3, 4]]
a
a[[2, 2]] = 8;
a</syntaxhighlight>
{{out}}
<pre>{{{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0,
0, 0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0,
0, 0, 0, 0}}}, {{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
0}, {0, 0, 0, 0, 0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0,
0, 0}, {0, 0, 0, 0, 0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0,
0, 0, 0, 0}, {0, 0, 0, 0, 0}}}}
15
{{{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 15, 0}, {0, 0,
0, 0, 0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0,
0, 0, 0, 0}}}, {{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
0}, {0, 0, 0, 0, 0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0,
0, 0}, {0, 0, 0, 0, 0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0,
0, 0, 0, 0}, {0, 0, 0, 0, 0}}}}
{{{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 15, 0}, {0, 0,
0, 0, 0}}, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0,
0, 0, 0, 0}}}, {{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
0}, {0, 0, 0, 0, 0}},
8, {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
0}}}}</pre>
 
=={{header|Nim}}==
Line 1,603 ⟶ 1,907:
Here are some examples:
 
<langsyntaxhighlight Nimlang="nim">import arraymancer
 
let c = [
Line 1,652 ⟶ 1,956:
# |1.0 1.0 1.0|
# |1.0 1.0 1.0|
# |1.0 1.0 1.0|</langsyntaxhighlight>
 
=={{header|Objeck}}==
{{trans|Java}}
<syntaxhighlight lang="objeck">class MultiArray {
function : Main(args : String[]) ~ Nil {
a4 := Int->New[5,4,3,2];
a4_size := a4->Size();
 
m := 1;
for(i := 0; i < a4_size[0]; i += 1;) {
for(j := 0; j < a4_size[1]; j += 1;) {
for(k := 0; k < a4_size[2]; k += 1;) {
for(l := 0; l < a4_size[3]; l += 1;) {
a4[i,j,k,l] := m++;
};
};
};
};
 
System.IO.Standard->Print("First element = ")->PrintLine(a4[0,0,0,0]);
a4[0,0,0,0] := 121;
 
for(i := 0; i < a4_size[0]; i += 1;) {
for(j := 0; j < a4_size[1]; j += 1;) {
for(k := 0; k < a4_size[2]; k += 1;) {
for(l := 0; l < a4_size[3]; l += 1;) {
System.IO.Standard->Print(a4[i,j,k,l])->Print(" ");
};
};
};
};
""->PrintLine();
}
}</syntaxhighlight>
 
{{output}}
<pre>
First element = 1
121 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use feature 'say';
 
# Perl arrays are internally always one-dimensional, but multi-dimension arrays are supported via references.
Line 1,702 ⟶ 2,046:
$d[2] = 'Wed';
@d[3..5] = @d[reverse 3..5];
say "@d"; # prints 'Mon Tue Wed Thu Fri Sat Sun'</langsyntaxhighlight>
 
=={{header|Phix}}==
Line 1,714 ⟶ 2,058:
sub-sequences, and can easily be shrunk or expanded, at any level, at any time.
 
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #004080;">sequence</span> <span style="color: #000000;">xyz</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">),</span><span style="color: #000000;">y</span><span style="color: #0000FF;">),</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span>
<!--</langsyntaxhighlight>-->
 
or if you prefer:
 
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #004080;">sequence</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">plane</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">space</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plane</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span>
<!--</langsyntaxhighlight>-->
 
Internally Phix uses reference counting with copy-on-write semantics, so the initial space allocated is x+y+z, and as
Line 1,731 ⟶ 2,075:
Note that all indexes are 1-based. You can also use negative indexes to count backwards from the end of the sequence.
 
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rqd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">3</span><span style="color: #0000FF;">),</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span><span style="color: #000000;">5</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">row</span> <span style="color: #000080;font-style:italic;">-- scratch var</span>
Line 1,743 ⟶ 2,087:
<span style="color: #000000;">rqd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">][</span><span style="color: #000000;">4</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- middle element of rqd[5][4] is now longer than the other two</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">rqd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">][</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span>
<!--</langsyntaxhighlight>-->
 
{{out}}
Line 1,753 ⟶ 2,097:
an easily readable fashion:
 
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #0000FF;">?</span><span style="color: #008000;">"==1=="</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rqd</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
Line 1,760 ⟶ 2,104:
<span style="color: #0000FF;">?</span><span style="color: #008000;">"==3=="</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rqd</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">})</span>
<!--</langsyntaxhighlight>-->
 
{{out}}
Line 1,797 ⟶ 2,141:
 
=={{header|Phixmonti}}==
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
0 ( 5 4 3 2 ) dim
Line 1,814 ⟶ 2,158:
0 10 repeat ( 5 4 2 ) sset
 
pstack</langsyntaxhighlight>
 
=={{header|Python}}==
Line 1,823 ⟶ 2,167:
 
Function <code>dict_as_mdarray</code> allows for the creation of an initialised multi-dimensional array of a given size. Note how indexing must use the round brackets of a tuple inside the square brackets of normal dict indexing:
<langsyntaxhighlight lang="python">>>> from pprint import pprint as pp # Pretty printer
>>> from itertools import product
>>>
Line 1,863 ⟶ 2,207:
(1, 2, 3, 3): 0.0,
(1, 2, 3, 4): 0.0}
>>></langsyntaxhighlight>
 
===Python: numpy library===
Line 1,871 ⟶ 2,215:
 
The default is row-major order (compatible with C). When dealing with Fortran storage order, care must be taken in order to get the same behavious as in Fortran:
<langsyntaxhighlight lang="python">import numpy as np
a = np.array([[1, 2], [3, 4]], order="C")
b = np.array([[1, 2], [3, 4]], order="F")
np.reshape(a, (4,)) # [1, 2, 3, 4]
np.reshape(b, (4,)) # [1, 2, 3, 4]
np.reshape(b, (4,), order="A") # [1, 3, 2, 4]</langsyntaxhighlight>
 
In Fortran, one would expect the result [1, 3, 2, 4].
<langsyntaxhighlight lang="python">>>> from numpy import *
>>>
>>> mdarray = zeros((2, 3, 4, 5), dtype=int8, order='F')
Line 1,959 ⟶ 2,303:
[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0]]]], dtype=int8)
>>> </langsyntaxhighlight>
 
=={{header|Quackery}}==
 
Quackery does not come supplied with multi-dimensional arrays. Presented here are two idiomatic implementations, the first using nests of nests, and the second using row major.
 
===Utility words common to both implementations===
 
When an <code>array</code> is created, each element of the array is preloaded with a datum. It could be initialised with something appropriate, such as e.g. zeros or empty strings, or <code>null</code> to indicate no value has been assigned yet.
 
When an <code>array</code> is created, its layout needs to be specified as a nest of numbers. For the array used in this task the layout is <code>[ 5 4 3 2 ]</code>.
 
Individual items in an array are also referred to with a nest of numbers, a "specifier". For the array used in this task the specifier will be four numbers, in the ranges <code>0...4</code>, <code>0...3</code>, <code>0...2</code>, and <code>0...1</code>, i.e. <code>[ 0 0 0 0 ] ... [ 4 3 2 1 ]</code>.
 
<code>[a]-></code>takes a specifier and a layout, and returns a number equal to the position of the item if the array were in row major.
 
<code>->[a]</code> is the converse operation; it takes a number and a layout, and returns a specifier.
 
To determine the number of items in an array from its layout, use <code>1 swap witheach *</code>
 
Note that in the nest-of-nests version arrays do not carry their layouts with them, so you would need to keep a note of the layout of an array somewhere if it will be required (i.e for the following example use.)
 
An example use for these would be using a <code>times</code> loop to iterate through every item of a multidimensional array without requiring nested <code>times</code> loops.
 
So <code>' [ 0 1 1 0 ] ' [ 5 4 3 2 ] [a]-></code> returns <code>8</code>, and <code>8 ' [ 5 4 3 2 ] ->[a]</code> returns <code>[ 0 1 1 0 ]</code>.
 
<syntaxhighlight lang="Quackery"> [ this ] is null ( --> [ )
 
[ 0 unrot
witheach
[ dip
[ behead rot ]
* + swap ]
drop ] is [a]-> ( [ [ --> n )
[ [] unrot
reverse
witheach
[ /mod rot
join swap ]
drop ] is ->[a] ( n [ --> [ )
</syntaxhighlight>
 
===Nest of nests===
 
<code>array</code> takes a datum with with to initialise each item in the array, and a layout, as described above, and returns an array.
 
<code>[peek]</code> takes a specifier as described above, and an array, and returns a datum.
 
<code>[poke]</code> takes a datum, an array, and a specifier, and returns an updated array, with the new datum in the specified location.
 
<syntaxhighlight lang="Quackery"> [ dip nested
reverse
witheach
[ of i if nested ] ] is array ( [ --> a )
 
[ witheach peek ] is [peek] ( [ a --> x )
 
[ dup dip
[ rot dip
[ -1 split drop
witheach
[ dip dup peek ] ] ]
reverse
witheach
[ dip swap poke ] ] is [poke] ( x a [ --> a )
</syntaxhighlight>
 
===Row major===
 
<code>array</code>, <code>[peek]</code>, and <code>[poke]</code> have the same behaviours as the nest-of-nests versions above.
 
<code>[layout]</code> takes an array and returns its layout.
 
<code>[size]</code> takes an array and returns the number of items in the array.
 
<syntaxhighlight lang="Quackery"> [ swap nested
over 1 swap
witheach *
of
2 pack ] is array ( x [ --> [ )
 
[ 0 peek ] is [layout] ( [ --> [ )
 
[ 1 peek size ] is [size] ( [ --> n )
 
[ swap unpack
unrot [a]-> peek ] is [peek] ( [ a --> x )
 
[ swap unpack
dip [ tuck [a]-> ]
rot dip
[ swap poke ]
swap 2 pack ] is [poke] ( x a [ --> a )</syntaxhighlight>
 
===Task===
 
The task code and output are the same for both versions.
 
<syntaxhighlight lang="Quackery"> null ' [ 5 4 3 2 ] array
say "[ 5 4 3 2 ] array created, initialised with nulls."
cr
cr
2 swap ' [ 3 2 1 0 ] [poke]
say "2 stored in [ 3 2 1 0 ]."
cr
4 swap ' [ 4 3 2 1 ] [poke]
say "4 stored in [ 4 3 2 1 ]."
cr
8 swap ' [ 4 3 2 1 ] [poke]
say "8 stored in [ 4 3 2 1 ]."
cr
cr
dup ' [ 0 0 0 0 ] [peek] echo
say " copied from [ 0 0 0 0 ]."
cr
dup ' [ 3 2 1 0 ] [peek] echo
say " copied from [ 3 2 1 0 ]."
cr
' [ 4 3 2 1 ] [peek] echo
say " copied from [ 4 3 2 1 ]."
cr</syntaxhighlight>
 
{{out}}
 
<pre>[ 5 4 3 2 ] array created, initialised with nulls.
 
2 stored in [ 3 2 1 0 ].
4 stored in [ 4 3 2 1 ].
8 stored in [ 4 3 2 1 ].
 
null copied from [ 0 0 0 0 ].
2 copied from [ 3 2 1 0 ].
8 copied from [ 4 3 2 1 ].</pre>
 
=={{header|Racket}}==
Line 1,967 ⟶ 2,444:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line># Raku supports multi dimension arrays natively. There are no arbitrary limits on the number of dimensions or maximum indices. Theoretically, you could have an infinite number of dimensions of infinite length, though in practice more than a few dozen dimensions gets unwieldy. An infinite maximum index is a fairly common idiom though. You can assign an infinite lazy list to an array and it will only produce the values when they are accessed.
 
my @integers = 1 .. Inf; # an infinite array containing all positive integers
Line 2,013 ⟶ 2,490:
my uint16 @d = 1 .. 10 # Since there are and only can be unsigned 16 bit integers, the optimizer will use a much more compact memory layout.
 
# Indices must be a positive integer. Negative indices are not permitted, fractional indices will be truncated to an integer.</langsyntaxhighlight>
 
=={{header|REXX}}==
Line 2,026 ⟶ 2,503:
element &nbsp; '''2, 0''' &nbsp; (and set that value to the variable &nbsp; '''g'''), &nbsp; one could code &nbsp; (note
the use of periods after the variable name and also between the indices to the array dimensions:
<langsyntaxhighlight lang="rexx">g = antenna.2.0</langsyntaxhighlight>
Memory allocation for stemmed arrays is not optimized, and the array elements are not contiguous.
 
The index to the array dimensions may be any integer, and indeed, even non-numeric &nbsp; (and possible non-viewable).
<langsyntaxhighlight lang="rexx"> a = '"' /*set variable A to a quote character ["]. */
b = '~' /*set variable B to a tilde character [~]. */
 
h.a.b = '+++' /*set variable H.".~ to three pluses [+++]. */</langsyntaxhighlight>
The REXX language does not do bounds checking, but if &nbsp; &nbsp; '''signal on novalue''' &nbsp; &nbsp; is in effect, it can be used to trap (read) references of array elements that haven't been assigned a value (at the time of the read reference).
<langsyntaxhighlight lang="rexx">/*REXX program shows how to assign and/or display values of a multi─dimensional array.*/
/*REXX arrays can start anywhere. */
y.=0 /*set all values of Y array to 0. */
Line 2,057 ⟶ 2,534:
say 'y.' || i || . || k || . || m '=' y.i.j.k.m
say 'y.'||i||.||k||.||m '=' y.i.j.k.m
say 'y.'i||.||k||.||m '=' y.i.j.k.m</langsyntaxhighlight>
{{out|output}}
<pre>y.0.0.0.0 = 0
Line 2,081 ⟶ 2,558:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring"># Project : Multi-dimensional array
 
a4 = newlist4(5,4,3,2)
Line 2,138 ⟶ 2,615:
t = newlist3(y,z,w)
next
return alist</langsyntaxhighlight>
Output:
<pre>First element = 1
Line 2,153 ⟶ 2,630:
 
Arrays in Scala always start (of course as the great Dijkstra in his [https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html EWD831] pointed out) from an index of zero and, insofar the target machine can handle, bounds can be checked automatically e.g. by the JVM (throwing an exception) or ES aka JavaScript (resulting "undefined").
<langsyntaxhighlight Scalalang="scala">object MultiDimensionalArray extends App {
 
// Create a regular 4 dimensional array and initialize successive elements to the values 1 to 120
Line 2,165 ⟶ 2,642:
println(a4.flatten.flatten.flatten.mkString(", "))
 
}</langsyntaxhighlight>
{{Out}}Best seen running in your browser either by [https://scalafiddle.io/sf/Lx6AG4S/0 (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/MF2p1z1fReyhjGcu4aY4Eg Scastie (remote JVM)].
 
Line 2,175 ⟶ 2,652:
===lists===
Multi-dimensional lists are easily handled by nesting. Let's define a helper proc to construct such lists using lrepeat:
<langsyntaxhighlight Tcllang="tcl">proc multilist {value args} {
set res $value
foreach dim [lreverse $args] {
Line 2,181 ⟶ 2,658:
}
return $res
}</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight Tcllang="tcl">% multilist x 2
x x
% multilist x 2 3
{x x x} {x x x}
% multilist x 2 3 4
{{x x x x} {x x x x} {x x x x}} {{x x x x} {x x x x} {x x x x}}</langsyntaxhighlight>
Both lset and lindex know how to access multi-dimensional lists:
<langsyntaxhighlight Tcllang="tcl">% set ml [multilist 0 2 3 4]
{{0 0 0 0} {0 0 0 0} {0 0 0 0}} {{0 0 0 0} {0 0 0 0} {0 0 0 0}}
% lset ml 1 2 3 11
Line 2,197 ⟶ 2,674:
{{0 0 0 0} {0 0 0 0} {0 0 0 0}} {{0 0 0 0} {0 0 0 0 12} {0 0 0 11}}
% lindex $ml 1 2 3
11</langsyntaxhighlight>
[http://www.tcl.tk/man/tcl/TclCmd/lsort.htm lsort] and [http://www.tcl.tk/man/tcl/TclCmd/lsearch.htm lsearch] are among other useful commands that support nested lists.
===arrays===
Tcl arrays are collections of variables, not collections of values: thus they cannot nest. But since keys are simply strings, multidimensional data can be kept like this:
<langsyntaxhighlight Tcllang="tcl">% array set x {
0,0 a
0,1 b
Line 2,222 ⟶ 2,699:
not c
% parray x $b,$a
x(1,0) = not c</langsyntaxhighlight>
Such an array can also be "sliced" with the array command:
<langsyntaxhighlight Tcllang="tcl">% array get x 1,*
1,0 c 1,1 d
% array names x 0,*
0,0 0,1</langsyntaxhighlight>
Note however that the order in which elements are returned from these operations is undefined! The last command might return {0,0 0,1} or {0,1 0,0} depending on how its keys are hashed, which is not under the programmer's control.
 
Using arrays like this for ordered data is suboptimal for this reason, and because iterating over elements is cumbersome. But it's a common technique for records:
<langsyntaxhighlight Tcllang="tcl">% array set players {
1,name Fido
1,score 0
Line 2,245 ⟶ 2,722:
Fido is green and has 0 points
Scratchy is pink and has 99 points
% </langsyntaxhighlight>
The interested reader should also be aware of the difference between arrays and [http://www.tcl.tk/man/tcl/TclCmd/dict.htm dict]ionaries, and know that the latter are often preferred for record-like structures.
 
=={{header|V (Vlang)}}==
 
<syntaxhighlight lang="v (vlang)">smd := [][]string{len: 4, init: []string{len:2, init: 'Hello'}}
imd := [][]int{len: 3, init: []int{len:4, init: it}}
mut mmd := [][]f64{len: 5, init: []f64{len: 5}}
mmd[0][2] = 2.0
mmd[1][3] = 4.2
mmd[2][4] = 1.8
mmd[3][0] = 5.0
mut omd := [][]bool{} // initialize without defining size
omd << [true, false, true]
println(smd)
println(imd)
println(mmd)
println(omd)</syntaxhighlight>
 
{{out}}
<pre>
[['Hello', 'Hello'], ['Hello', 'Hello'], ['Hello', 'Hello'], ['Hello', 'Hello']]
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
[[0, 0, 2, 0, 0], [0, 0, 0, 4.2, 0], [0, 0, 0, 0, 1.8], [5, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
[[true, false, true]]
</pre>
 
=={{header|Wren}}==
Line 2,253 ⟶ 2,754:
 
Otherwise what was said in the Kotlin preamble applies more or less to Wren.
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
 
// create a 4 dimensional list of the required size and initialize successive elements to the values 1 to 120
Line 2,285 ⟶ 2,786:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,292 ⟶ 2,793:
 
121 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
</pre>
 
=={{header|X86-64 Assembly}}==
I was originally going to omit this, because multi-dimentional arrays simply don't exist in Assembly. But I decided to at least show how to use them.
<syntaxhighlight lang="asm">
option casemap:none
 
printf proto :qword, :vararg
exit proto :dword
 
ROW_LEN equ (4*4)
MEM_SIZE equ 4
 
.data
;; A 2d array - 2 rows, 4 columns
;; int twodimen[2][4] = { {0,1,2,3},
;; {4,5,6,7}};
twodimen db 48 dup (0)
tpl db "%d",13,10,0
 
.code
main proc
local cols:qword
lea rbx, twodimen
mov cols, 0
;; Forgive me for the multiple loops, I'm just to lazy to
;; do the conditional jumps required for 2 for loops. -.-
@1:
mov rcx, cols
mov dword ptr [rbx+0*ROW_LEN + rcx*MEM_SIZE], ecx ;; first row, rcx column
inc cols
cmp cols, 3
jle @1
 
mov cols, 0
mov rdx, 4
@2:
mov rcx, cols
mov dword ptr [rbx+1*ROW_LEN + rcx*MEM_SIZE], edx ;; second row, rcx column
inc cols
inc edx
cmp cols, 3
jle @2
invoke printf, CSTR("--> Printing columns in row 1",10)
mov cols, 0
@3:
mov rcx, cols
mov esi, dword ptr [rbx+0*ROW_LEN + rcx*MEM_SIZE]
lea rdi, tpl
call printf
inc cols
cmp cols, 3
jle @3
 
invoke printf, CSTR("--> Printing columns in row 2",10)
mov cols, 0
@4:
mov rcx, cols
mov esi, dword ptr [rbx+1*ROW_LEN + rcx*MEM_SIZE]
lea rdi, tpl
call printf
inc cols
cmp cols, 3
jle @4
 
 
mov rax, 0
xor edi, edi
call exit
leave
ret
main endp
</syntaxhighlight>
{{out}}
<pre>
--> Printing columns in row 1
0
1
2
3
--> Printing columns in row 2
4
5
6
7
</pre>
So as stated previously. Multi-dimentional arrays DO NOT exist in Assembly. However one way to reference them is as displayed above.. It's syntax is ..
<pre>
row * row length + column * member size
</pre>
However, a C compiler for example doesn't use such a method. Infact, a compiler will generally output something like..
<syntaxhighlight lang="asm">
mov dword ptr [rbp-48], 0
mov dword ptr [rbp-44], 1
.....
mov ecx, dword ptr [rbp-48]
</syntaxhighlight>
If you're curious you can use gcc's -S command line option to print out AT&T syntax'd ASM from C/C++ files or something like Cutter if you're more into the Intel syntax.
 
=={{header|XPL0}}==
Arrays can have any number of dimensions.
 
Pointers are used to access beyond the first dimension, thus the concept
of row-major versus column-major doesn't apply. A consequence of this is
that multi-dimensional arrays require more memory than an array in the C
language. Another consequence is that accessing multi-dimensional array
elements can be faster by dereferencing pointers than by calculating
offsets with multiplies. (This was especially true on the 6502 processor
where XPL0 was born.)
 
The last dimension (rightmost index) addresses contiguous memory, for
cache efficiency. Arrays always start at index 0, and there is no
automatic bounds checking. Out-of-bounds errors on multi-dimensional
arrays are very likely to cause memory violation exceptions (segmentation
faults) because of an invalid pointer.
 
Multi-dimensional arrays are supported for all three data types: integer,
real, and character. Multi-dimensional character arrays use 32-bit integer
pointers for each dimension except the last, which are 8-bit bytes.
 
<syntaxhighlight lang="xpl0">
int A(5,4,3,2);
[A(3,1,0,1):= 3100;
A(3,1,0,1):= A(3,1,0,1)+1;
IntOut(0, A(3,1,0,1));
]</syntaxhighlight>
 
{{out}}
<pre>
3101
</pre>
9,476

edits