多次元配列

二次元配列

配列は同じデータ型の変数をまとめて扱うことができる機能です。
前ページの配列で説明した配列は一次元配列というもので、単純な並びのデータの場合に有効です。

では、例えば以下のような表を配列で扱うことを考えてみます。


英語 国語 数学
A君 60 75 82
B君 78 70 80
C君 80 64 68

プログラミングには関係ありませんが、このような表の縦の並びを、横の並びをと言います。
(エクセルなどでは頻繁に使われる語です)

前回までの知識だけでデータを扱うとすれば例えば以下のようになります。


int[] personA = new int[] { 60, 75, 82 };
int[] personB = new int[] { 78, 70, 80 };
int[] personC = new int[] { 80, 64, 68 };

これでもとりあえず問題はありません。
しかし、今は3人分のデータだけですが、これが30人だとどうでしょうか?
そのたびに新しい配列変数を宣言して増やしていかねばなりません。
手間が掛かるだけでなく、扱う人数に比例してコードの記述量も増えてしまいます。

こういった表形式のデータは二次元配列を使用すると扱いやすくなります。


//二次元配列
int[,] record = new int[,]
{
    { 60, 75, 82 },
    { 78, 70, 80 },
    { 80, 64, 68 }
};

二次元配列は配列宣言時の角括弧[]の中にカンマ(,)を一つ記述します。
newの後のintの角括弧内にも書くのを忘れないようにしましょう。

二次元配列は表形式のデータを扱うのに便利です。
各要素へのアクセスは以下のように添え字として二つの数値を使用します。


static void Main(string[] args)
{
    int[,] record = new int[,]
    {
        { 60, 75, 82 },
        { 78, 70, 80 },
        { 80, 64, 68 }
    };

    //A君の国語の成績
    Console.WriteLine(record[0, 1]);

    //C君の英語の成績
    Console.WriteLine(record[2, 0]);

    Console.ReadLine();
}
75
80

二次元配列の各要素の添え字は以下のようになります。

[0, 0] [0, 1] [0, 2]
[1, 0] [1, 1] [1, 2]
[2, 0] [2, 1] [2, 2]

要素を指定した後は変数と同じく値の取り出しも代入も自由にできます。

二次元以上の配列をまとめて多次元配列と呼びます。

二次元配列の初期化

上のサンプルコードでは初期化リストを使用して二次元配列の宣言と同時に初期化を行っています。
一次元配列の時と同じく、初期化リストを使用する場合は要素数を省略できます。
省略しない場合は以下のように書きます。


int[,] record = new int[3, 3]
{
    { 60, 75, 82 },
    { 78, 70, 80 },
    { 80, 64, 68 }
};

要素数の指定と初期化リストのデータ数とが合わない場合はエラーになります。

ちなみに初期化リストの最後のカンマは省略しても構いませんし、記述しても構いません。


int[,] arr1 = new int[,]
{
    { 10, 20, 30 },
    { 40, 50, 60 },
    { 70, 80, 90 }   //←カンマ省略
};

int[,] arr2 = new int[,]
{
    { 10, 20, 30 },
    { 40, 50, 60 },
    { 70, 80, 90 }, //←カンマ記述
};

一次元配列の時と同じく初期化リストを使用しないことも可能です。
その場合は要素数の指定は省略できません。
また、各要素はデータ型の既定値で初期化されます。
int型の既定値は0です。


//すべての要素が「0」で初期化される
int[,] arr = new int[2, 3];

Console.WriteLine(arr[1, 2]); //0

newの省略

宣言時に初期化リストを使用する場合は、newとその後のデータ型の指定を省略することができます。


int[,] arr = 
{
    { 10, 20, 30 },
    { 40, 50, 60 }
};

三次元配列

一次元、二次元とくれば当然三次元配列も存在します。
三次元配列は二次元配列の「縦×横」に「奥行」の概念を加えたようなものです。


int[,,] threeArray = new int[2, 3, 4]
{
    {
        { 1, 2, 3, 4 },
        { 5, 6, 7, 8 },
        { 9, 10, 11, 12 }
    },
    {
        { 13, 14, 15, 16 },
        { 17, 18, 19, 20 },
        { 21, 22, 23, 24 }
    }
};

宣言は角括弧内のカンマを一つ増やすだけです。
初期化リストの記述方法も上記を参考にしてください。

三次元配列の要素数の指定順は「奥行×縦×横」となります。
三次元配列は以下のようなイメージとなります。

三次元配列のイメージ

四次元以上の配列

四次元以上の配列も同様の方法で記述可能ですが、ここまでくると配列で扱うのはあまり適切とは言えません。
もちろん四次元のデータモデルを扱うのならば四次元配列が適切な場合もありますが、単純に複数のデータをまとめて扱いたいという場合はクラス構造体といった別の方法を用いたほうが良いケースが多くなります。

多次元配列の要素数取得

一次元配列の要素数はLengthプロパティで取得できますが、多次元配列にLengthプロパティを使用するとすべての次元をひっくるめた要素数が得られます。
それぞれの次元の要素数を取得したい場合はGetLengthメソッド(関数)を使用します。


int[,] arr = new int[,] {
    { 0, 1, 2 },
    { 3, 4, 5 }
};

//すべての要素数の取得
int lengthAll = arr.Length;

//一次元目の要素数
int length1 = arr.GetLength(0);

//二次元目の要素数
int length2 = arr.GetLength(1);

Console.Write("すべての要素数: ");
Console.WriteLine(lengthAll);
Console.Write("一次元目の要素数: ");
Console.WriteLine(length1);
Console.Write("二次元目の要素数: ");
Console.WriteLine(length2);
すべての要素数: 6
一次元目の要素数: 2
二次元目の要素数: 3

ジャグ配列(配列の配列)

C#では多次元配列の表現方法が二種類あります。
ひとつは上で説明したもので、角括弧[]の中にカンマを書いて次元数を指定します。
C#で「多次元配列」というと通常はこれを指します。

もうひとつはジャグ配列(配列の配列)と呼ばれるもので、配列の要素の中にさらに配列を入れる方法です。


int[][] arr = new int[][]
{
    new int[] { 10, 20, 30 },
    new int[] { 40, 50 },
    new int[] { 60, 70, 80, 90 }
};

初期化リストの中でさらにnewすることで、配列の要素の中にさらに配列を入れています。

普通の多次元配列はすべての行(表で言えば横の並び)の要素数は同じになりますが、ジャグ配列は行の要素数が異なっても構いません。

配列とジャグ配列のイメージ

上記は初期化リストを使用していますが、初期化リストを使用しない場合の宣言方法は列(表で言えば縦の並び)の数のみを指定します。
行の数はそれぞれの列で異なるためここでは指定できません。


//3列のジャグ配列を宣言
int[][] jaggedArr = new int[3][];

後は通常の配列と同様に初期化したり各要素にアクセスすることができます。


int[][] jaggedArr = new int[3][];

jaggedArr[0] = new int[] { 10, 20, 30 };
jaggedArr[1] = new int[] { 40, 50 };

jaggedArr[2] = new int[4];
jaggedArr[2][0] = 60;
jaggedArr[2][1] = 70;
jaggedArr[2][2] = 80;
jaggedArr[2][3] = 90;

ジャグ配列の要素数の取得

ジャグ配列は「配列の配列」なので、要素数は列ごとにバラバラです。
特定の列の要素数を取得するには先頭要素にアクセスした後にLengthプロパティを使用します。


int[][] arr = new int[][]
{
    new int[] { 10, 20, 30 },
    new int[] { 40, 50 },
    new int[] { 60, 70, 80, 90 }
};

//列の数
Console.WriteLine(arr.Length);

//0行目の要素数
Console.WriteLine(arr[0].Length);

//1行目の要素数
Console.WriteLine(arr[1].Length);

//2行目の要素数
Console.WriteLine(arr[2].Length);
3
3
2
4