.NET TIPS

配列を独自の順序でソート(並べ替え)するには?

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

 数値や文字列の配列のソート(並べ替え)は、Arrayクラス(System名前空間)の静的なメソッドであるSortメソッドにより既定の順序でソートできるが、本稿では独自の順序により配列をソートする方法について解説する。

Array.Sortメソッドによる配列のソート

 まず、既定の順序によるソートついて簡単に見ておこう。配列の要素が数値型や文字列型をソートする場合には、Array.Sortメソッドのパラメータに、その配列を指定するだけだ。次にそのサンプル・プログラムを示す。

// arraysort.cs

using System;
using System.Collections;

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

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

// コンパイル方法:csc arraysort.cs
Array.Sortメソッドにより文字列の配列をソートするC#のサンプル・プログラム(arraysort.cs)
 
' arraysort.vb

Imports System
Imports System.Collections

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

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

' コンパイル方法:vbc arraysort.vb
Array.Sortメソッドにより文字列の配列をソートするVB.NETのサンプル・プログラム(arraysort.vb)

 このようにしてソートできる配列は、その要素のクラスがIComparableインターフェイス(System名前空間)を実装している必要がある。ほとんどの数値型や文字列型(Stringクラス)は、このインターフェイスを実装している(このインターフェイスについては後述)。

独自の比較ルーチンを実装するCompareメソッド

 Arrayクラスにおける配列のソートは、配列から取り出した2つの要素について、その大小をそれぞれの要素から得られる比較可能な値(数値の場合にはその値、文字の場合にはその文字コードの値など)により比較し並べ替えるという作業の繰り返しである(正確には、クイックソートと呼ばれるアルゴリズムが用いられている)。独自の順序によるソートというのは、2つの要素を比較してその大小を決定する部分を独自に実装するということにほかならない。

 ArrayクラスのSortメソッドでは、このような2つの要素の比較ルーチンを外部から提供できる仕組みを持っている。この仕組みを利用するには、第2パラメータとしてIComparerインターフェイス(System.Collections名前空間)のオブジェクトを指定するSortメソッドを使用する。

Array.Sort(strArray, icompareObject);

 IComparerインターフェイスは、次のようなシグネチャを持つCompareメソッドを定義しているインターフェイスである(以下はC#による定義)。

int Compare(object x, object y)

 このインターフェイスを実装したクラスのオブジェクトをSortメソッドに渡すことにより、そのクラスのCompareメソッドがSortメソッドの内部で要素の比較時に使用されるという仕組みである。

 Compareメソッドは、パラメータにより受け取った2つのオブジェクト(xとy)を比較し、xがyより小さい場合には戻り値として負の値を、等しい場合には0を、そしてxがyより大きい場合には正の値を返すという役割が決められている。

文字列の長さによるソート

 ここでは例として、文字列の長さによるソート(文字列の短い順に並べ替える)を考えてみよう。この場合には、Compareメソッドの定義は次のようになる(C#の場合。VB.NETについては後述のサンプル・プログラムを参照)。

public int Compare(object x, object y) {
  string str1 = (string)x;
  string str2 = (string)y;

  return str1.Length - str2.Length;
}

 Compareメソッドのパラメータはobject型でなければならないため、比較に先立って、それぞれをキャストして文字列型に戻す必要がある(ここでは割愛しているが、キャストに失敗する場合には例外をスローするのが一般的である)。Lengthプロパティは文字列の長さを得るためのものだ。2つの文字列の長さを引き算することにより、Compareメソッドに期待されている戻り値を得ることができる。

 このCompareメソッドを含む、IComparerインターフェイスを実装したクラスを利用して文字列の配列をソートするサンプル・プログラムを次に示す。

// strlensort.cs

using System;
using System.Collections;

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

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

public class StrLenComparer : IComparer {
  public int Compare(object x, object y) {
    string str1 = (string)x;
    string str2 = (string)y;

    return str1.Length - str2.Length;
  }
}

// コンパイル方法:csc strlensort.cs
文字列の長さにより配列をソートするC#のサンプル・プログラム(strlensort.cs)
 
' strlensort.vb

Imports System
Imports System.Collections

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

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

Public Class StrLenComparer
    Implements IComparer
  Public Function Compare(ByVal x As Object,ByVal y As Object) As Integer Implements IComparer.Compare
    Dim str1 As String = CType(x, String)
    Dim str2 As string = CType(y, String)

    Return str1.Length - str2.Length
  End Function
End Class

' コンパイル方法:vbc strlensort.vb
文字列の長さにより配列をソートするVB.NETのサンプル・プログラム(strlensort.vb)

 もし、文字列の長さの長い順にソートした場合には、最後のreturn文における引き算の順序を入れ替えて「str2.Length - str1.Length」とすればよい。

 なお、ここではArrayクラスのSortメソッドについて取り上げたが、可変長の配列として利用できるArrayListクラス(System.Collections名前空間)のSortメソッドもArrayクラスとまったく同じ仕組みを持っており、IComparerオブジェクトにより独自の順序でソートが可能だ。

IComparableインターフェイス

 ちなみに、先に示した「Array.Sort(strArray)」によるソートは、実際にはCompareクラス(System.Collections名前空間)クラスのComparerメソッドを比較ルーチンとして利用している(もちろん、このCompareクラスもIComparerインターフェイスを実装している)。つまり、Array.Sortメソッドのデフォルトの比較ルーチンが、CompareクラスのCompareメソッドだということだ。

 そしてさらに、このCompareクラスのCompareメソッドでは、比較対象となっているオブジェクトが持つCompareToメソッドを呼び出すことにより、その比較を行う。CompareToメソッドは、IComparableインターフェイスで定義されているメソッドである。パラメータで配列のみを指定したArray.Sortメソッドを利用する場合に、その配列がIComparableインターフェイスを実装している必要があると先に述べたのはこのためである。IComparableインターフェイスとCompareToメソッドについては、「TIPS:自作クラスによる配列をソート(並べ替え)するには?」で解説している。End of Article

カテゴリ:クラス・ライブラリ 処理対象:配列
使用ライブラリ:Arrayクラス(System名前空間)
使用ライブラリ:IComparableインターフェイス(System名前空間)
使用ライブラリ:IComparerインターフェイス(System.Collections名前空間)
使用ライブラリ:ArrayListクラス(System.Collections名前空間)
使用ライブラリ:Compareクラス(System.Collections名前空間)
関連TIPS:自作クラスによる配列をソート(並べ替え)するには?
 
この記事と関連性の高い別の.NET TIPS
自作クラスによる配列をソート(並べ替え)するには?
自作クラスによる配列をソート(並べ替え)するには?(LINQ版)
大文字/小文字を区別しないで文字列を比較するには?
ハッシュテーブル(Dictionaryクラス)を値でソートするには?
[ASP.NET]DataGridコントロールにソート機能を追加するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム 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メールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

Insider.NET 記事ランキング

本日 月間
ソリューションFLASH