【C#】List (リスト)

■ Listについて、あれこれ

ArrayListについて

 * .NET 2.0以前は、ArrayListしかなかった。
 * ArrayListは、object型のデータが入るので何でも入れられるが、取り出すときにキャストする必要がある
 * 間違ってキャストすると例外で落ちるが、コンパイル時には発見し辛いのでやっかい。

 →ゆえに、「ジェネリック List<T>」を使いましょ。

■ リスト要素内に特定のデータがあるかどうか判定する

 * Any()を使う
 * Any()については、以下を参照のこと
https://blogs.yahoo.co.jp/dk521123/20248181.html

■ リスト要素内に指定した値が存在しているかどうか

 * Exists()を使う
 * Contains()の方がいいかも...

サンプル

 * 単語が母音だったら「An」それ以外なら「A」を付加して表示する
 * 正規表現やstring.StartsWith()でもできると思うけど...
https://blogs.yahoo.co.jp/dk521123/8566072.html
private void button1_Click(object sender, EventArgs e)
{
    List<char> list = new List<char>()
    {
        'A', 'a', 'I', 'i', 'U', 'u', 'E', 'e', 'O', 'o',
    };

    if (!char.IsLetter(this.textBox1.Text[0]))
    {
        this.label1.Text = "アルファベットじゃないです";
    }
    else if (list.Exists(x => x == this.textBox1.Text[0]))
    {
        this.label1.Text = "A " + this.textBox1.Text;
    }
    else
    {
        this.label1.Text = "An " + this.textBox1.Text;
    }
}

■ ReadOnlyのリストを作成する

 * Array.AsReadOnly()を使用する

サンプル

Form1.cs
private void button1_Click(object sender, EventArgs e)
{
    var list = Array.AsReadOnly(
        new double[] { 3.0, 2.0, 3.0, 3.0, 3.0, 4.0 });

    var obj = new Average();

    string text = string.Empty;

    foreach (var data in list)
    {
        text =
            text + " " + this.obj.Calculate(data).ToString();
    }

    this.label1.Text = text;
}
Average.cs
public class Average
{
    private IList<double> dataList;

    public Average()
    {
       this.dataList = new List<double>();
    }
    public double Calculate(double data)
    {
        this.dataList.Add(data);

        double average;
        if (this.dataList.Count < 3)
        {
            return double.NaN;
        }
        else if (this.dataList.Count > 3)
        {
            this.dataList.RemoveAt(0);
        }

        double sum = 0;
        foreach (var tempData in this.dataList)
        {
            sum = sum + tempData;
        }
        average = sum / this.dataList.Count;

        return average;
    }
}

■ リスト要素を削除する

 * RemoveAll()を使う

サンプル

* Any()、RemoveAll()を使ったサンプル
public class Person
{
    public string Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

private void button1_Click(object sender, EventArgs e)
{
    List<Person> list = new List<Person>()
    {
        new Person() {Id = "001", Name = "Mike", Age = 22, },
        new Person() {Id = "002", Name = "Sam", Age = 18, },
        new Person() {Id = "xxx", Name = "Tom", Age = 32, },
    };

    if (list.Any(x => x.Id == this.textBox1.Text))
    {
        list.RemoveAll(x => x.Id == this.textBox1.Text);
        this.label1.Text = "Id : " + this.textBox1.Text + " を削除しました";
    }
    else
    {
        this.label1.Text = "そんなデータない";
    }

    this.dataGridView1.DataSource = list;
}

■ List同士をマージ(連結)する

 * AddRange()を使う
http://msdn.microsoft.com/ja-jp/library/z883w3dc(v=vs.80).aspx

サンプル

Personクラスは、「リスト要素を削除する」の時と同じ
private void button1_Click(object sender, EventArgs e)
{
    var people1 = new List<Person>()
        {
            new Person() {Id = "001", Name = "Mike", Age = 22, },
            new Person() {Id = "002", Name = "Sam", Age = 18, },
            new Person() {Id = "004", Name = "Tom", Age = 32, },
        };
    var people2 = new List<Person>()
        {
            new Person() {Id = "003", Name = "John", Age = 43, },
            new Person() {Id = "005", Name = "Dave", Age = 34, },
            new Person() {Id = "006", Name = "Kite", Age = 27, },
        };

    people1.AddRange(people2);

    var output = string.Empty;
    foreach(var person in people1)
    {
        output = output + 
            person.Id.ToString() + " " + 
            person.Name + "(" + person.Age.ToString() + ")" +
            System.Environment.NewLine;
    }

    this.label1.Text = output;
}

■ 重複する要素を取り除く

 * Distinct()を使う

サンプル

List<int> ages = new List<int> { 21, 46, 46, 55, 17, 21, 55, 55 };
List<int> distinctAges = ages.Distinct().ToList();

■ 条件付きでリストのインデックスを取得

 * FindIndex()を使用する

サンプル

List<Person> list = new List<Person>()
{
  new Person() {Id = "001", Name = "Mike", Age = 22, },
  new Person() {Id = "002", Name = "Sam", Age = 18, },
  new Person() {Id = "xxx", Name = "Tom", Age = 32, },
};

int index = list.ToList().FindIndex(x => x.Id == "xxx");

■ クローンを作成する

 * newする時の引数にリストを与えてあげるだけ。

サンプル

List<Person> cloneList = new List<Person>(list);

関連記事

C# / コレクション

Dictionary (ディクショナリ)
https://blogs.yahoo.co.jp/dk521123/21978660.html
Concurrentコレクション ~ スレッドセーフなコレクション ~
https://blogs.yahoo.co.jp/dk521123/38017014.html
BlockingCollection ~ Producer-Consumerパターン ~
https://blogs.yahoo.co.jp/dk521123/37943991.html