.NET TIPS

自作クラスによる配列をソート(並べ替え)するには?

デジタルアドバンテージ
2004/10/15

 「TIPS:配列を独自の順序でソート(並べ替え)するには?」では、IComparerインターフェイス(System.Collections名前空間)を実装したクラスを用意することで、文字列配列のソートを行った。この方法では、任意のクラスのオブジェクトからなる配列も、独自の順序でソートすることができる。

 例えば、次のようなWordクラスがあるとしよう(C#の場合。VB.NETについては以下のサンプル・プログラムを参照)。

public class Word {
  public string data;
  public Word(string s) { data = s; }
}

 このクラスの配列を、そのメンバである文字列「data」の長さによりソートするには、「TIPS:配列を独自の順序でソート(並べ替え)するには?」で解説している方法により、次のようにして行うことができる。

// wordsort1.cs

using System;
using System.Collections;

public class Word {
  public string data;
  public Word(string s) { data = s; }
}

public class WordSort1 {
  static void Main() {
    Word[] wordArray = {
      new Word("いろは"),
      new Word("にほえと"),
      new Word("ちりぬるを"),
      new Word("わか"),
      new Word("よたれそ"),
      new Word("つねならむ"),
    };
    IComparer wordComp = new WordComparer();
    Array.Sort(wordArray, wordComp);

    foreach (Word w in wordArray) {
      Console.WriteLine(w.data);
    }
    // 出力:
    // わか
    // いろは
    // よたれそ
    // にほえと
    // つねならむ
    // ちりぬるを

  }
}

public class WordComparer: IComparer {
  public int Compare(object x, object y) {
    Word word1 = (Word)x;
    Word word2 = (Word)y;

    return word1.data.Length - word2.data.Length;
  }
}

// コンパイル方法:csc wordsort1.cs
IComparerインターフェイスを実装したクラスによりWordクラスの配列をソートするC#のサンプル・プログラム(wordsort1.cs)
 
' wordsort1.vb

Imports System
Imports System.Collections

Public Class Word
  Public Dim data As String
  Public Sub New(ByVal s As String)
    data = s
  End Sub
End Class

Public Class WordSort1
  Shared Sub Main()
    Dim wordArray As Word() = { _
      New Word("いろは"), _
      New Word("にほえと"), _
      New Word("ちりぬるを"), _
      New Word("わか"), _
      New Word("よたれそ"), _
      New Word("つねならむ") _
    }
    Dim wordComp As IComparer = New WordComparer()
    Array.Sort(wordArray, wordComp)

    For Each w As Word In wordArray
      Console.WriteLine(w.data)
    Next
    ' 出力:
    ' わか
    ' いろは
    ' よたれそ
    ' にほえと
    ' つねならむ
    ' ちりぬるを
  End Sub
End Class

Public Class WordComparer
    Implements IComparer
  Public Function Compare(ByVal x As Object,ByVal y As Object) As Integer Implements IComparer.Compare
    Dim word1 As Word = CType(x, Word)
    Dim word2 As Word = CType(y, Word)

    Return word1.data.Length - word1.data.Length
  End Function
End Class

' コンパイル方法:vbc wordsort1.vb
IComparerインターフェイスを実装したクラスによりWordクラスの配列をソートするVB.NETのサンプル・プログラム(wordsort1.vb)

 自作クラスのオブジェクトからなる配列をソートするには、このようなIComparerインターフェイスを用いた方法に加え、IComparableインターフェイス(System名前空間)を用いた方法でも可能だ。次にこれについて解説する。

IComparableインターフェイスのCompareToメソッド

 「TIPS:配列を独自の順序でソート(並べ替え)するには?」の最後で解説しているように、パラメータとして配列のみを指定するArray.Sortメソッドは、最終的には指定された配列の要素に対してCompareToメソッドを呼び出すことにより、2つの要素の大小を比較して並べ替えを行う。このCompareToメソッドを定義しているのがIComparableインターフェイスである。

 IComparableインターフェイスのCompareToメソッドのシグネチャは次のようになっている(以下はC#による定義)。

int CompareTo(object obj)

 「Array.Sort(配列)」の実行は、配列内のある要素に対して、このCompareToメソッドを呼び出す。このとき、比較対象となる配列内の別の要素がパラメータとして渡される。CompareToメソッドは、IComparerインターフェイスのCompareメソッドと同様に、比較結果により負の値、0、正の値のいずれかを戻り値として返さなければならない。

 つまり、自作クラスにIComparableインターフェイスを実装し、CompareToメソッドを定義しておけば、そのクラスのオブジェクトの配列は「Array.Sort(配列)」の呼び出しによりソートできるというわけである。前掲のTIPSでも述べているように、ほとんどの数値型や文字列型(Stringクラス)は、このIComparableインターフェイスを実装している。

IComparableインターフェイスを実装したソート可能なクラス

 冒頭で示したWordクラスにIComparableインターフェイスを実装し、そのメンバである文字列「data」の長さにより、その配列をソートするサンプル・プログラムを次に示す。

// wordsort2.cs

using System;
using System.Collections;

public class Word : IComparable {
  public string data;
  public Word(string s) { data = s; }

  public int CompareTo(object obj) {
    Word word1 = this;
    Word word2 = (Word)obj;

    return word1.data.Length - word2.data.Length;
  }
}

public class WordSort2 {
  static void Main() {
    Word[] wordArray = {
      new Word("いろは"),
      new Word("にほえと"),
      new Word("ちりぬるを"),
      new Word("わか"),
      new Word("よたれそ"),
      new Word("つねならむ"),
    };
    Array.Sort(wordArray);

    foreach (Word w in wordArray) {
      Console.WriteLine(w.data);
    }
    // 出力:
    // わか
    // いろは
    // よたれそ
    // にほえと
    // つねならむ
    // ちりぬるを
  }
}

// コンパイル方法:csc wordsort2.cs
IComparableインターフェイスを実装したWordクラスの配列をソートするC#のサンプル・プログラム(wordsort2.cs)
 
' wordsort2.vb

Imports System
Imports System.Collections

Public Class Word
    Implements IComparable
  Public Dim data As String
  Public Sub New(ByVal s As String)
    data = s
  End Sub

  Public Function Compare(ByVal obj As Object) As Integer Implements IComparable.CompareTo
    Dim word1 As Word = Me
    Dim word2 As Word = CType(obj, Word)

    return word1.data.Length - word2.data.Length
  End Function
End Class

Public Class WordSort2
  Shared Sub Main()
    Dim wordArray As Word() = { _
      New Word("いろは"), _
      New Word("にほえと"), _
      New Word("ちりぬるを"), _
      New Word("わか"), _
      New Word("よたれそ"), _
      New Word("つねならむ") _
    }
    Array.Sort(wordArray)

    For Each w As Word In wordArray
      Console.WriteLine(w.data)
    Next
    ' 出力:
    ' わか
    ' いろは
    ' よたれそ
    ' にほえと
    ' つねならむ
    ' ちりぬるを
  End Sub
End Class

' コンパイル方法:vbc wordsort2.vb
IComparableインターフェイスを実装したWordクラスの配列をソートするVB.NETのサンプル・プログラム(wordsort2.vb)

 このプログラムで示しているように、CompareToメソッドでは、そのインスタンス自身(C#では「this」、VB.NETでは「Me」により参照可能)とパラメータで渡された別のインスタンスとの比較を行うことになる。

 なお、ここではArrayクラスのSortメソッドについて取り上げたが、可変長の配列として利用できるArrayListクラス(System.Collections名前空間)のSortメソッドも、各要素のIComparableインターフェイス実装を利用してソートを行う(実際には、その内部でArray.Sortメソッドを使ってソートを行っている)。End of Article

カテゴリ:クラス・ライブラリ 処理対象:配列
使用ライブラリ:Arrayクラス(System名前空間)
使用ライブラリ:IComparerインターフェイス(System.Collections名前空間)
使用ライブラリ:IComparableインターフェイス(System名前空間)
使用ライブラリ:ArrayListクラス(System.Collections名前空間)
関連TIPS:配列を独自の順序でソート(並べ替え)するには?
 
この記事と関連性の高い別の.NET TIPS
配列を独自の順序でソート(並べ替え)するには?
自作クラスによる配列をソート(並べ替え)するには?(LINQ版)
C#で配列を宣言するには?
配列のサイズを変更するには?
ハッシュテーブル(Dictionaryクラス)を値でソートするには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間