.NET TIPS

自作クラスによる配列をソート(並べ替え)するには?(LINQ版)[3.5、C#、VB]

デジタルアドバンテージ 遠藤 孝信
2009/05/28

 「TIPS:自作クラスによる配列をソート(並べ替え)するには?」では、IComparableインターフェイス(System名前空間)を実装することにより、自作クラスの配列をソートする方法について解説したが、.NET Framework 3.5(Visual Studio 2008)以降では、LINQの機能を使って、もっと簡単に自作クラスの配列をソートできる。

OrderByメソッドによるソート

 LINQでは、コレクションのソートはOrderByメソッドによって可能だ。このメソッドは配列(=System名前空間のArrayクラス)に対しても呼び出すことができる*

* 配列に対するOrderByメソッドは、実際には拡張メソッドとして実装されており、その実体はEnumerableクラス(System.Linq名前空間)で実装されている。

 以下のサンプル・プログラムでは、独自のWordクラスを定義し、そのオブジェクトの配列を、dataフィールドの値(文字列)の長さでソートしている。OrderByメソッドの引数には、ソート時の比較に使用されるキーを返すラムダ式を記述する。

// linqsort1.cs

using System;
using System.Linq;

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

public class LinqSort1 {
  static void Main() {

    Word[] wordArray = {
      new Word("むつき"),
      new Word("きさらぎ"),
      new Word("やよい"),
      new Word("うづき"),
      new Word("さつき"),
      new Word("みなづき"),
      new Word("ふみづき"),
      new Word("はづき"),
      new Word("ながつき"),
      new Word("かんなづき"),
      new Word("しもつき"),
      new Word("しわす"),
    };

    // dataフィールドの文字列の長さでソート
    wordArray = wordArray.OrderBy(n => n.data.Length)
                         .ToArray();

    foreach (Word w in wordArray) {
      Console.WriteLine(w.data);
    }
    // 出力:
    // むつき
    // やよい
    // うづき
    // さつき
    // はづき
    // しわす
    // きさらぎ
    // みなづき
    // ふみづき
    // ながつき
    // しもつき
    // かんなづき
  }
}

// コンパイル方法:csc linqsort1.cs
' linqsort1.vb

Imports System
Imports System.Linq

Public Class Word

  Public Dim data As String

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

Public Class LinqSort1
  Shared Sub Main()

    Dim wordArray As Word() = { _
      New Word("むつき"), _
      New Word("きさらぎ"), _
      New Word("やよい"), _
      New Word("うづき"), _
      New Word("さつき"), _
      New Word("みなづき"), _
      New Word("ふみづき"), _
      New Word("はづき"), _
      New Word("ながつき"), _
      New Word("かんなづき"), _
      New Word("しもつき"), _
      New Word("しわす") _
    }

    ' dataフィールドの文字列の長さでソート
    wordArray = wordArray.OrderBy(Function(n)  n.data.Length) _
                         .ToArray()

    For Each w As Word In wordArray
      Console.WriteLine(w.data)
    Next
    ' 出力:
    ' むつき
    ' やよい
    ' うづき
    ' さつき
    ' はづき
    ' しわす
    ' きさらぎ
    ' みなづき
    ' ふみづき
    ' ながつき
    ' しもつき
    ' かんなづき
  End Sub
End Class

' コンパイル方法:vbc linqsort1.vb
OrderByメソッドによるWord配列のソート(上:C#、下:VB)

 なお、OrderByメソッドの戻り値は、このプログラムの場合にはIEnumerable<Word>型(VBではIEnumerable(Of Word)型)となるが、ArrayToメソッドにより配列に変換できる。

 ちなみに、OrderByメソッドによるソートは「安定した並べ替え」と呼ばれるもので、2つの要素のソート・キー(ここでは文字列の長さ)が等しい場合、ソート結果は元の順序が保持される。

複数の条件でソート

 OrderByメソッドでのソート結果に対して、さらにソート条件を追加したい場合には、OrderByメソッドに続けてThenByメソッドを呼び出せばよい。

 以下のサンプル・プログラムでは、Wordオブジェクトのdataフィールドの長さでソートし、さらにThenByメソッドにより“アイウエオ順”でソートしている。これにより、dataフィールドの長さが同じ要素は、それらの要素間でさらにアイウエオ順でソートされる。

// linqsort2.cs

using System;
using System.Linq;

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

public class LinqSort2 {
  static void Main() {

    Word[] wordArray = {
      new Word("むつき"),
      new Word("きさらぎ"),
      new Word("やよい"),
      new Word("うづき"),
      new Word("さつき"),
      new Word("みなづき"),
      new Word("ふみづき"),
      new Word("はづき"),
      new Word("ながつき"),
      new Word("かんなづき"),
      new Word("しもつき"),
      new Word("しわす"),
    };

    // dataフィールドの文字列の長さでソートし、
    // さらに、アイウエオ順でソート
    wordArray = wordArray.OrderBy(n => n.data.Length)
                         .ThenBy(n => n.data)
                         .ToArray();

    foreach (Word w in wordArray) {
      Console.WriteLine(w.data);
    }
    // 出力:
    // うづき
    // さつき
    // しわす
    // はづき
    // むつき
    // やよい
    // きさらぎ
    // しもつき
    // ながつき
    // ふみづき
    // みなづき
    // かんなづき
  }
}

// コンパイル方法:csc linqsort2.cs
' linqsort2.vb

Imports System
Imports System.Linq

Public Class Word

  Public Dim data As String

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

Public Class LinqSort2
  Shared Sub Main()

    Dim wordArray As Word() = { _
      New Word("むつき"), _
      New Word("きさらぎ"), _
      New Word("やよい"), _
      New Word("うづき"), _
      New Word("さつき"), _
      New Word("みなづき"), _
      New Word("ふみづき"), _
      New Word("はづき"), _
      New Word("ながつき"), _
      New Word("かんなづき"), _
      New Word("しもつき"), _
      New Word("しわす") _
    }

    ' dataフィールドの文字列の長さでソートし、
    ' さらに、アイウエオ順でソート
    wordArray = wordArray.OrderBy(Function(n)  n.data.Length) _
                         .ThenBy(Function(n) n.data) _
                         .ToArray()

    For Each w As Word In wordArray
      Console.WriteLine(w.data)
    Next
    ' 出力:
    ' うづき
    ' さつき
    ' しわす
    ' はづき
    ' むつき
    ' やよい
    ' きさらぎ
    ' しもつき
    ' ながつき
    ' ふみづき
    ' みなづき
    ' かんなづき
  End Sub
End Class

' コンパイル方法:vbc linqsort2.vb
文字列の長さ+アイウエオ順でソート(上:C#、下:VB)

 なお、逆順にソートしたい場合には、OrderByメソッド/ThenByメソッドの代わりに、OrderByDescendingメソッド/ThenByDescendingメソッドを使用する。End of Article

利用可能バージョン:.NET Framework 3.5以降
カテゴリ:クラス・ライブラリ 処理対象:配列
カテゴリ:クラス・ライブラリ 処理対象:LINQ
使用ライブラリ:Arrayクラス(System名前空間)
使用ライブラリ:Enumerableクラス(System.Linq名前空間)
関連TIPS:自作クラスによる配列をソート(並べ替え)するには?

この記事と関連性の高い別の.NET TIPS
自作クラスによる配列をソート(並べ替え)するには?
Listの要素を並べ替えるには?[C#/VB]
配列を独自の順序でソート(並べ替え)するには?
WPF:DataGridやListViewなどにデータをソートして表示するには?
[ASP.NET]GridViewコントロールのヘッダにソート方向を表示するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム 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 記事ランキング

本日 月間