Multi-dimensional array: Difference between revisions

m
No edit summary
m (→‎{{header|Wren}}: Minor tidy)
 
(13 intermediate revisions by 10 users not shown)
Line 20:
Show all output here, (but you may judiciously use ellipses to shorten repetitive output text).
<br><br>
 
=={{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 29 ⟶ 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 35 ⟶ 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 50 ⟶ 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 69 ⟶ 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 92 ⟶ 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 113 ⟶ 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 142 ⟶ 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 151 ⟶ 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 166 ⟶ 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 179 ⟶ 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 214 ⟶ 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 241 ⟶ 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 253 ⟶ 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 267 ⟶ 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 296 ⟶ 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 332 ⟶ 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 362 ⟶ 383:
return 0;
}
</syntaxhighlight>
</lang>
Output :
<pre>
Line 371 ⟶ 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 438 ⟶ 459:
return 0;
}</langsyntaxhighlight>
Output :
<pre>
Line 452 ⟶ 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 460 ⟶ 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 481 ⟶ 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 500 ⟶ 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 509 ⟶ 530:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <vector>
 
Line 577 ⟶ 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 742 ⟶ 763:
nativeExample();
customArray();
}</langsyntaxhighlight>
{{out}}
<pre>Static array: [1, 2, 3]
Line 764 ⟶ 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 811 ⟶ 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 828 ⟶ 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 846 ⟶ 912:
! Reshape and show the array.
"Reshaped: " print
{ 5 4 3 2 } reshape .</langsyntaxhighlight>
{{out}}
<pre>
Line 930 ⟶ 996:
The word <code> darray </code> can be used as follows
 
<langsyntaxhighlight 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 ]
Line 936 ⟶ 1,002:
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>
</lang>
 
Tested on Gforth and VFX Forth - both 64 bit Linux.
 
<langsyntaxhighlight lang="forth">
\ Values used to avoid locals or some confusing stack juggling.
\ They could be replaced by locals if preferred.
Line 1,015 ⟶ 1,081:
 
print-4d test4d
</syntaxhighlight>
</lang>
<pre>
[
Line 1,051 ⟶ 1,117:
</pre>
 
<langsyntaxhighlight lang="forth">
-4567 1 2 3 3 test4d ! ok
1 2 3 3 test4d @ . -4567 ok
 
print-4d test4d
</syntaxhighlight>
</lang>
<pre>
[
Line 1,095 ⟶ 1,161:
=={{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 1,104 ⟶ 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 1,117 ⟶ 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 1,132 ⟶ 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 1,137 ⟶ 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,192 ⟶ 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,205 ⟶ 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,241 ⟶ 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,274 ⟶ 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,303 ⟶ 1,400:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>First element = 1
Line 1,316 ⟶ 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,322 ⟶ 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,342 ⟶ 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,360 ⟶ 1,457:
 
Another approach "nests" arrays inside other arrays:
<langsyntaxhighlight lang="javascript">
function array(length) {
var rest= Array.prototype.slice.call(arguments);
Line 1,369 ⟶ 1,466:
}
}
}</langsyntaxhighlight>
This approach is superficially simpler but may turn out to be considerably slower.
 
Line 1,408 ⟶ 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,414 ⟶ 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,422 ⟶ 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,445 ⟶ 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,457 ⟶ 1,554:
end
else []
end;</langsyntaxhighlight>
 
For exampe:
<langsyntaxhighlight lang="jq">ary | dimensions
#=> [5,4,3,2]</langsyntaxhighlight>
 
=={{header|Julia}}==
Line 1,467 ⟶ 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,561 ⟶ 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,583 ⟶ 1,680:
pstack
 
"End " input</langsyntaxhighlight>
 
=={{header|Kotlin}}==
Line 1,591 ⟶ 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,616 ⟶ 1,713:
print(f.format(a4[i][j][k][l]))
 
}</langsyntaxhighlight>
{{out}}
<pre>First element = 1
Line 1,625 ⟶ 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,638 ⟶ 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,649 ⟶ 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,694 ⟶ 1,791:
show4dArray(t)
t[1][1][1][1] = true
show4dArray(t)</langsyntaxhighlight>
{{out}}
<pre>Printing 4D array in 2D...
Line 1,767 ⟶ 1,864:
=={{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:
<langsyntaxhighlight Mathematicalang="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</langsyntaxhighlight>
{{out}}
<pre>{{{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0,
Line 1,810 ⟶ 1,907:
Here are some examples:
 
<langsyntaxhighlight Nimlang="nim">import arraymancer
 
let c = [
Line 1,859 ⟶ 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,909 ⟶ 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,921 ⟶ 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,938 ⟶ 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,950 ⟶ 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,960 ⟶ 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,967 ⟶ 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 2,004 ⟶ 2,141:
 
=={{header|Phixmonti}}==
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
0 ( 5 4 3 2 ) dim
Line 2,021 ⟶ 2,158:
0 10 repeat ( 5 4 2 ) sset
 
pstack</langsyntaxhighlight>
 
=={{header|Python}}==
Line 2,030 ⟶ 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 2,070 ⟶ 2,207:
(1, 2, 3, 3): 0.0,
(1, 2, 3, 4): 0.0}
>>></langsyntaxhighlight>
 
===Python: numpy library===
Line 2,078 ⟶ 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 2,166 ⟶ 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 2,174 ⟶ 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,220 ⟶ 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,233 ⟶ 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,264 ⟶ 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,288 ⟶ 2,558:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring"># Project : Multi-dimensional array
 
a4 = newlist4(5,4,3,2)
Line 2,345 ⟶ 2,615:
t = newlist3(y,z,w)
next
return alist</langsyntaxhighlight>
Output:
<pre>First element = 1
Line 2,360 ⟶ 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,372 ⟶ 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,382 ⟶ 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,388 ⟶ 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,404 ⟶ 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,429 ⟶ 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,452 ⟶ 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,460 ⟶ 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,492 ⟶ 2,786:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,499 ⟶ 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