プログラム初心者のためのC#入門 #6 配列

# #6 配列
配列の話に入る前に次の問題にしたがってコードを書いてみてください．

---
**問題**

|安藤|小林|戸田|中野|渡辺|
|:-:|:-:|:-:|:-:|:-:|
|83|59|72|96|81|
上の表は英語のテストを受けた5人の得点だ．この5人全員の合計点数，平均を出力してください．

---
皆さんはこの問題を解くためにどんなコードを書きますか．

```ArraySample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArraySample
{
    class Program
    {
        static void Main(string[] args)
        {
            int andoScore = 83;
            int kobayashiScore = 59;
            int todaScore = 72;
            int nakanoScore = 96;
            int watanabeScore = 81;

            int sum = andoScore + kobayashiScore
                + todaScore + nakanoScore + watanabeScore;
            double average = (double)sum / 5;

            Console.WriteLine("合計点は" + sum);
            Console.WriteLine("平均点は" + average);
        }
    }
}
```

こんな感じでしょうか．もしくは点数をリテラルで打ち込んで`int sum = 83 + 59 + 72 + 96 + 81;`のようにしてしまったかもしれませんね．今回は合計と平均を出すだけなのでわざわざ変数を用意してやるほどのことではないのですが，もし変数に入れて取り扱った方が便利な場合でも，このままでは扱いづらいので**配列**というものを使います．

##配列
配列は同じ型のデータをまとめて扱うためのデータ構造です．同じ変数名でいくつかのデータを扱い，インデックスによって欲しいデータを呼び出せるので，今回のように同じ型のデータがいくつもある場合は簡単にデータを扱うことができます．余談ですが，文字列を扱うstring型もchar型の配列です．文字が連続したものを，char型の配列としてひとまとめにして扱っています．なんとなく配列のイメージができましたか？
配列のようにいくつもの同じ型のデータをまとめて扱えるようにしたものを**コレクション**といい，ほかには**List**などがあります．また，コレクションの中のデータの事を要素と呼びます．

```
型[] 変数名 = new 型[要素数];
```

型に`[]`を付けると配列になります．例えばint型の配列なら`int[]`，doubleの配列なら`double[]`といった感じです．

```cs
int[] array = new int[5];
```

これで，arrayという要素数5のint型の配列ができました．各要素にアクセスするためには角括弧とインデックス番号を使います．arrayの1番目，arrayの2番目，...といったようにアクセスできます．

```cs
array[1] = 2;
array[2] = 4;
array[3] = 8;
array[4] = 16;
array[5] = 32;
```

あれ？`array[5]`にアクセスできません．最後の要素にはアクセスできない仕様なのでしょうか？そんなことありません．`array[5]`なんて元からないんです．**インデックス番号は0から4まで**，1つ目の要素は`array[0]`，2つ目の要素は`array[1]`というように1つずれています．ちょっとややこしいので気を付けましょう．ということで，全要素を初期化しなおしてみましょう．

```cs
array[0] = 1;
array[1] = 2;
array[2] = 4;
array[3] = 8;
array[4] = 16;
```

これで全要素を初期化できました．ですが，このように一つずつアクセスして初期化していくのは面倒なので，初期化する値が決まっているなら変数の定義と同時に初期化してしまいましょう．

```cs
int[] array = new int[5] { 1, 2, 4, 8, 16 };
```

このように記述することで，一気に初期化も済ませることができます．さらにもっと手を抜いて書くと

```cs
var array = new[] { 1, 2, 4, 8, 16 };
```

このように書くこともできます．`var`は型推論という，代入されたものによって型を推測してくれるという便利なものです．int型の配列であるのは`=`の後ろによってわかるのでvarと書けば`array`を`int[]`型として扱ってくれます．同様に`1`，`2`，`4`，`8`，`16`によってint型の要素が5つであることはわかるので，`int[5]`まで書かなくても`[]`だけでも使えます．

さて，ここで先ほどの問題を解いてみましょう．

```ArraySample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArraySample
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] scores = new int[5] { 83, 59, 72, 96, 81 };
            int sum = 0;
            for (int i = 0; i < score.Length; i++)
            {
                sum += scores[i];
            }
            double average = (double)sum / scores.Length;

            Console.WriteLine("合計点は" + sum);
            Console.WriteLine("平均点は" + average);
        }
    }
}
```

上のコードを見てわかると思いますが，配列はループ処理ととても相性が良いです．繰り返し回数を数える`i`を配列のインデックスとしても使えるので，かなり簡単に全要素にアクセスすることができます．また，`配列.Length`で配列の長さ(要素数)を取得できます．
そして，foreach文を使うともっとスマートに書くことができます．

```ArraySample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArraySample
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] scores = new int[5] { 83, 59, 72, 96, 81 };
            int sum = 0;
            foreach (int score in scores)
            {
                sum += score;
            }
            double average = (double)sum / scores.Length;

            Console.WriteLine("合計点は" + sum);
            Console.WriteLine("平均点は" + average);
        }
    }
}
```

foreach文はコレクションの長さだけ繰り返し処理を実行します．`scores`の中の要素を`score`としてそれぞれ扱い，`score`を`sum`に足しています．これで`scores`内の全要素の合計が`sum`の中に入っていることになります．foreach文はコレクションを扱うためにあるようなものなので，コレクションを用いるならそこそこお世話になると思うので使い方を押さえておきましょう．

##LINQ
それではここで，さらに上を行きたい人向けの話をしましょう．
C#には**LINQ**という，コレクションを手軽に扱うことができるものがあります．このLINQのためにC#を使っているという人もいるみたいです．LINQを使うときは，`using System.Linq;`が書かれているか確認しましょう．書かれていなければ追加しましょう．

```ArraySample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArraySample
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] scores = new int[5] { 83, 59, 72, 96, 81 };
            int sum = scores.Sum();
            double average = scores.Average();

            Console.WriteLine("合計点は" + sum);
            Console.WriteLine("平均点は" + average);
        }
    }
}
```
`配列.Sum()`，`配列.Average()`で合計，平均を取得することができます．LINQについてはまた取り上げようと思いますが，興味のある人は勉強してみてください．

次回は[関数](https://qiita.com/17t7037t/items/9ccc6db4e3188d5f986b)について説明しようと思います．

##練習問題
1，2，4，8，16，32，64を半径とする円の面積と円周の長さをそれぞれ求めてください．円周率は`Math.PI`を使ってください．

<details><summary>解答例</summary><div>
foreach文使ってますか？

```ArraySample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArraySample
{
    class Program
    {
        static void Main(string[] args)
        {
            var radii = new[] { 1, 2, 4, 8, 16, 32, 64 };

            foreach (var radius in radii)
            {
                Console.WriteLine("半径 : " + radius);
                Console.WriteLine("面積 : " + Math.PI * radius * radius);
                Console.WriteLine("円周 : " + 2 * Math.PI * radius);
                Console.WriteLine();
            }
        }
    }
}
```

</div></summary>