配列変数
大量のデータを扱う場合の処理
前回までの内容で、C#言語のアルゴリズムの三大要素がすべて出そろいました。しかし、これだけでは十分なプログラムができるわけではありません。プログラムを記述するためにはアルゴリズムとデータ構造という二大要素があります。
ここからは、いよいよデータ構造について説明していきます。実用的なプログラムを作るときに必要なデータ構造はたくさんありますが、ここでは大量のデータを扱う場合に必要な配列(はいれつ)について説明します。C# では、変数を用いて大量のデータを扱う場合に配列変数(はいれつへんすう)を用います。
サンプルプログラム(配列を使わない場合)
配列変数について詳しく説明する前に、まずは以下のプログラムを入力・実行してみてください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample501
{
class Program
{
static void Main(string[] args)
{
double one, two, three;
double sum, avg; // 合計値、平均値を入れる変数
one = 1.2;
two = 3.7;
three = 4.1; // 変数への代入
Console.WriteLine(one + " " + two + " " + three);
sum = one + two + three; // 合計値の計算
avg = sum / 3.0; // 平均値の計算
Console.WriteLine("合計値:" + sum);
Console.WriteLine("平均値:" + avg);
}
}
}
合計値:9
平均値:3
このケースは数値が3つだからよいですが、もっと増えたらどうなるでしょう? four、five と次々に変数の数を増やしていかなくてはなりません。しかし、以下のように配列を使うと、大変楽になります。
サンプルプログラム(配列を使う場合)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample502
{
class Program
{
static void Main(string[] args)
{
double[] d = new double[3];
d[0] = 1.2;
d[1] = 3.7;
d[2] = 4.1; // 変数への代入
double sum, avg; // 合計値、平均値を入れる変数
sum = 0.0;
for (int i = 0; i < d.Length; i++)
{
Console.Write(d[i] + " ");
sum += d[i];
}
Console.WriteLine();
avg = sum / d.Length;
Console.WriteLine("合計値:" + sum);
Console.WriteLine("平均値:" + avg);
}
}
}
実行結果は Sample501 と同じです。若干プログラムが長くなりましたが、変数が5個・10個・100個と増えたときを考えると、こちらのほうがプログラムの変更が容易です。
配列変数の宣言
13行目に出てくる double[] d = new double[3]; という記述が配列変数の宣言です。配列変数とは、同一の名前で多数のデータを格納できる変数のことで、単に配列とも呼ばれます。宣言の書式は以下のとおりです。
この例では d が変数名、3 が配列の大きさ(要素数)です。これにより d[0]・d[1]・d[2] という3つの double 型変数が使用可能になります。
添字
[] の中に書いてある数字を添字(そえじ)と言います。例えば「d[1] = 3.7;」という処理は、配列の2番目の要素に 3.7 という値を代入することを意味します(図5-1・図5-2)。添字は必ず 0 から始まりますので、配列の大きさが3の場合は 0・1・2 の3つになります。
図5-1. 配列の宣言(左)/図5-2. 配列変数への値の代入(右)
配列変数を使うメリットは、この添字に整数型変数を使えることにあります。19〜22行目の for ループで添字に変数 i を用いているため、配列の大きさが変わっても for 文の条件式を変えるだけで対応できます。
配列の大きさ
19行目に出てくる d.Length は、配列変数の要素数を表します。この場合 d の要素は3つなので、d.Length は 3 となります。
配列の初期化
サンプルプログラム
配列変数の宣言と初期化は、以下のように一度にまとめて行うこともできます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample503
{
class Program
{
static void Main(string[] args)
{
int[] n = { 5, 4, 3, 2, 1 };
string[] s = { "ABC", "DEF", "GHI" };
int i;
// 整数型配列変数 n の成分表示
for (i = 0; i < n.Length; i++)
{
Console.Write(n[i] + " ");
}
Console.WriteLine();
// 文字列型配列変数 s の成分表示
for (i = 0; i < s.Length; i++)
{
Console.Write(s[i] + " ");
}
Console.WriteLine();
}
}
}
ABC DEF GHI
13〜14行目では配列を生成すると同時に値を代入しています。例えば n については以下のような処理と同等です。
// 上記は以下の処理と同等
int[] n = new int[5];
n[0] = 5;
n[1] = 4;
n[2] = 3;
n[3] = 2;
n[4] = 1;
文字列変数 s についても同様で、3つの要素を持ち、s[0] から s[2] にそれぞれ「ABC」「DEF」「GHI」が代入されます。
foreach ループ
サンプルプログラム
4日目で for や while をはじめとする繰り返し処理について説明しました。それらと同様に、配列の内容の出力に使える繰り返し処理があります。それが foreach(フォーイーチ) です。for ループよりもシンプルに配列のすべての要素を取得できます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample504
{
class Program
{
static void Main(string[] args)
{
int[] n = { 1, 2, 3, 4 };
foreach (int i in n)
{
Console.Write("{0} ", i);
}
Console.WriteLine();
}
}
}
foreach の書式
処理
}
これにより、配列変数の値が一つずつ変数に入っていきます。すべての値が変数に入ると、ループが終了します。配列の内容をすべて出力する場合は、for ループよりもこちらの方が簡潔に書けます。
多次元配列
サンプルプログラム
次に、配列変数の応用である多次元配列(たじげんはいれつ)について説明しましょう。多次元配列とは、複数の添字を持つことができる配列変数です。ここでは最も基本となる二次元配列の例を紹介します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample505
{
class Program
{
static void Main(string[] args)
{
int[,] a = new int[3, 4];
int m, n;
// 二次元配列に値を代入
for (m = 0; m < 3; m++)
{
for (n = 0; n < 4; n++)
{
a[m, n] = m + n;
}
}
// 二次元配列の値を出力
for (m = 0; m < 3; m++)
{
for (n = 0; n < 4; n++)
{
Console.Write("a[{0},{1}]={2} ", m, n, a[m, n]);
}
Console.WriteLine();
}
}
}
}
a[1,0]=1 a[1,1]=2 a[1,2]=3 a[1,3]=4
a[2,0]=2 a[2,1]=3 a[2,2]=4 a[2,3]=5
二次元配列
二次元配列 a には、2つの添字をつけることができます。これにより、行と列を持つ2次元のデータ構造を作ることができます(図5-3)。
図5-3. 二次元配列のイメージ
2つの添字の間は ,(コンマ)で区切ります。同様にして、3次元・4次元といった配列を作ることも可能です。
| 種類 | 宣言 | 要素へのアクセス例 |
|---|---|---|
| 二次元配列 | int[,] a = new int[3, 4]; | a[1, 2] = 2; |
| 三次元配列 | int[,,] a = new int[3, 4, 5]; | a[1, 2, 3] = 2; |
| 四次元配列 | int[,,,] a = new int[3, 4, 5, 6]; | a[1, 2, 3, 4] = 2; |
多次元配列の利用範囲は非常に広く、さまざまな表や座標などのデータを表すために使用されます。わかりやすい例でいうと、表計算のような処理は二次元配列を用いれば非常に簡単に実現できます。
ジャグ配列
サンプルプログラム
Sample505 では長方形の形になる二次元配列を紹介しましたが、各行の要素数が不揃いな配列を作ることもできます。これをジャグ配列と言います。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sample506
{
class Program
{
static void Main(string[] args)
{
int[][] a = new int[][]
{
new int[] { 0, 1 },
new int[] { 2 },
new int[] { 3, 4, 5, 6 }
};
// 成分の表示
for (int m = 0; m < a.Length; m++)
{
for (int n = 0; n < a[m].Length; n++)
{
Console.Write(a[m][n] + " ");
}
Console.WriteLine();
}
}
}
}
2
3 4 5 6
このように、各行の要素数がばらばらになるケースも扱えます。図にすると以下のようなイメージです(図5-4)。
図5-4. ジャグ配列のイメージ