ジャグ配列とは「配列の配列」を表す用語。ジャグ配列では配列の特定の次元の各要素が参照する配列の要素数が異なる場合がある。
ジャグ配列(Jagged Array)とは「配列の配列」(配列を要素とする配列)を表す用語。配列の特定の次元の各要素が参照する配列の要素数が異なっていても構わない(例えば、2次元の配列であれば、各行の列数が異なっていても構わない)。そのため配列の全体としての見た目が「ギザギザ」(jagged)に見える(ことがある)ことから、このように呼ばれている。
ジャグ配列は「多次元配列」の一種と考えることもできる。多次元配列の特定の次元の各要素が格納する配列の要素数が同一である場合(例えば、2次元配列の各行の列数が同じ場合)、そのような配列を特に「矩形配列」(rectangular array)と呼ぶことがある。これに対して、「配列の配列」(ジャグ配列)ではある次元において各要素が参照する配列の要素数が異なる場合もあり、その場合、配列全体の見た目は矩形にはならない。
C#など、多次元配列(矩形配列)とジャグ配列を明確に区別している言語も存在する。その一方で、ジャグ配列を利用して多次元配列を取り扱う言語もある。
C#でのジャグ配列の作成例を以下に示す。
class Program
{
static void Main(string[] args)
{
int[][] jarray = new int[2][];
jarray[0] = new int[] { 1, 2 };
jarray[1] = new int[] { 3, 4, 5 };
for (int i = 0; i < jarray.Length; i++)
{
for (int j = 0; j < jarray[i].Length; j++)
{
Console.WriteLine($"jarray[{i}][{j}]: {jarray[i][j]}");
}
}
Console.ReadKey();
}
}
この例では、int配列を要素とする(1次元)配列jarray(jagged array)を作成して、その各要素をint配列で初期化した後に、その値をfor文の二重ループで利用している。変数jarrayが参照しているのはあくまでも1次元の配列であり、その要素がさらに1次元の配列を参照している。そして、「jarray[i][j]」としているように、ジャグ配列の要素にはインデクサーを重ねて、それがあたかも2次元配列であるかのようにアクセスできる。
これに対して、上と同様なことをC#の多次元配列を使って行うコードは次のようになる。
class Program
{
static void Main(string[] args)
{
int[,] rarray = new int[2, 3] // rectangular array
{
{ 1, 2, 0 },
{ 3, 4, 5 }
};
Console.WriteLine($"length(all): {rarray.Length}");
foreach (var item in rarray)
{
Console.WriteLine(item);
}
for (var i = 0; i < rarray.GetLength(0); i++)
{
for (var j = 0; j < rarray.GetLength(1); j++)
{
Console.WriteLine($"rarray[{i}, {j}]: {rarray[i, j]}");
}
}
Console.ReadKey();
}
}
まず、C#の多次元配列は矩形配列となるので、上のコードでは最初の行の3番目の要素には「0」を入れている(ジャグ配列にはなかった配列要素)。null許容型の配列を作成してnullをセットした方がよいかもしれない。大きく異なるのは配列要素へのアクセス方法で、ジャグ配列では「jarray[x][y]」だったのが「rarray[x, y]」のようになる点だ。
また、配列の長さを求めている最初のConsole.WriteLineメソッド呼び出しでは「rarray.Length」としているが、これは配列全体の長さを取得するものだ。各次元の要素数を取得するには、forループで行っているようにGetLengthメソッドを使用する。最後に、foreach文を使うと、ループをネストさせることなく配列の各要素にアクセス可能だ(ただし、インデックス情報などは得られないので、細かな制御を行うのなら、その下のfor文のようにループをネストさせることになるだろう)。
このようにC#ではジャグ配列と多次元配列ではその扱い方が明確に異なっているので、用途に合わせて適切なものを使うようにしたい。
なお、実際にはジャグ配列の初期化はもっと簡単に次のように書いてもよい。ジャグ配列の初期化の方法についてはMSDNの「ジャグ配列 (C# プログラミング ガイド)」を参照されたい。
int[][] jarray = {
new int[] { 1, 2 },
new int[] { 3, 4, 5 }
};
また、LINQのSelectメソッドを使うとforeach文でもインデックスを取得/利用できる。
class Program
{
static void Main(string[] args)
{
int[][] jarray = {
new int[] { 1, 2 },
new int[] { 3, 4, 5 }
};
foreach (var iarray in jarray.Select((v, i) => new { v, i }))
{
foreach (var item in iarray.v.Select((v, j) => new { v, j }))
{
Console.WriteLine($"jarray[{iarray.i}][{item.j}]: {item.v}");
}
}
Console.ReadKey();
}
}
参考までに同じことをJavaScriptで記述したものを以下に示しておこう。
var jarray = [
[1, 2],
[3, 4, 5]
];
jarray.forEach((iarray, i) => {
iarray.forEach((item, j) => console.log(`jarray[${i}][${j}]: ${item}`))
})
Pythonでは次のようになる。
jarray = [
[1, 2],
[3, 4, 5]
]
for i, iarray in enumerate(jarray):
for j, item in enumerate(iarray):
print("jarray[", i, "][", j, "]: ", item, sep="")
なお、Python 3.6では文字列補間が可能になったことから最後のprint関数はもっと簡潔に「print(f"jarray[{i}][{j}]: {item}")」と記述可能だ。
ジャグ配列とは「配列の配列」(配列を要素とする配列)を表す用語。ジャグ配列では配列の特定の次元の各要素が参照する配列の要素数が異なっていても構わない。C#のように多次元配列と明確に区別している言語もあれば、ジャグ配列を用いて多次元配列を実現している言語もある。
Copyright© Digital Advantage Corp. All Rights Reserved.