Listのソート/カスタム比較

Listのソート (IComparer を用いたカスタムソート) - C#

IComparerを用いたListのカスタムソートのコードを紹介します。

概要

こちらの記事では、Comparisionを実装してクラスオブジェクトのリストをソートするコードを紹介しましたが、 より複雑なソートのロジックを実装する場合は、IComparerインターフェイスを持つソート用のクラスを実装する方法が適しています。
この記事ではIComparer を利用したListのカスタムソートのコードを紹介します。

プログラム例

UI

下図のUIを用意します。テキストボックス1つ、ボタンを1つ設置します。

コード

FormMain.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ListSort
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button3_Click(object sender, EventArgs e)
    {
      List<Info> InfoList = new List<Info>();
      Info inf;

      inf = new Info();
      inf.Name = "Penguin";
      inf.value = 10;
      InfoList.Add(inf);

      inf = new Info();
      inf.Name = "Duck";
      inf.value = 5;
      InfoList.Add(inf);

      inf = new Info();
      inf.Name = "Pigion";
      inf.value = 5;
      InfoList.Add(inf);

      inf = new Info();
      inf.Name = "Swallow";
      inf.value = 8;
      InfoList.Add(inf);

      inf = new Info();
      inf.Name = "Spallow";
      inf.value = 5;
      InfoList.Add(inf);

      inf = new Info();
      inf.Name = "Hawk";
      inf.value = 18;
      InfoList.Add(inf);

      ValueCompare vc = new ValueCompare();
      InfoList.Sort(vc);

      for (int i = 0; i < InfoList.Count; i++) {
        textBox_Output.Text += string.Format("{0:s}:{1:d}\r\n",
          InfoList[i].Name, InfoList[i].value);
      }
    }

  }
}

infoクラスの実行コードです。Nameとvalueのメンバ変数を定義しています。
Info.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ListSort
{
  public class Info
  {
    public string Name;
    public int value;
  }
}
ValueCompare.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ListSort
{
  public class ValueCompare : System.Collections.Generic.IComparer<Info>
  {
    public int Compare(Info x, Info y)
    {
      if (x.value < y.value) {
        return -1;
      }
      else if (x.value > y.value) {
        return 1;
      }
      else {
        if (x.Name.Length < y.Name.Length) {
          return -1;
        }
        else if (x.Name.Length > y.Name.Length) {
          return 1;
        }
        else {
          return 0;
        }
      }
    }
  }
}

解説

FormMain.cs

List<Info> InfoList = new List<Info>();
InfoクラスのListを宣言してインスタンスを作成します。

inf = new Info();
inf.Name="Penguin";
inf.value=100;
InfoList.Add(inf);
...
にて、InfoListにInfoクラスの要素を追加します。

ValueCompare vc = new ValueCompare();
InfoList.Sort(Compare);
リストをソートします。引数のIComparerにICompaererのインターフェイスを持つクラスのインスタンスを与えます。

for (int i = 0; i < InfoList.Count; i++ ) {
  textBox_Output.Text += string.Format("{0:s}:{1:d}\r\n",
  InfoList[i].Name, InfoList[i].value);
}
InfoListの要素を先頭から順番にTextBoxに表示します。

info.cs

IComparerインターフェイスを持つクラスを宣言します。
public class ValueCompare : System.Collections.Generic.IComparer<Info>

ValueCompare.cs

以下のコードがソートの比較用メソッドです。valueの値の昇順にソートします。valueが同じ場合はNameの文字数で昇順にソートします。
public int Compare(Info x, Info y)
{
  if (x.value < y.value) {
    return -1;
  }
  else if (x.value > y.value) {
    return 1;
  }
  else {
    if (x.Name.Length < y.Name.Length) {
      return -1;
    }
    else if (x.Name.Length > y.Name.Length) {
      return 1;
    }
    else {
      return 0;
    }
  }
}

実行結果

アプリケーションを実行すると下図の画面が表示されます。


コードを実装したボタン(今回の場合は[Exec3])をクリックします。下図の結果がテキストボックスに表示されます。valueの値で昇順にvalueが同じ値の場合はNameの文字数で昇順にソートされていることを確認できます。


著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2012-01-19
iPentec all rights reserverd.