for WPF developers
Home Profile Tips 全記事一覧

ThenBy 拡張メソッドで昇順に並べ替える条件を加える

(2017/03/14 11:03:13 created.)

ThenBy 拡張メソッドは、OderBy 拡張メソッドで並べ替えた後のシーケンスに対してさらに並べ替えの条件を付け加えるためのメソッドです。ThenBy 拡張メソッドの定義を見てみましょう。

System.Linq.Enumerable クラスでの定義
  1. public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector);
  2.  
  3. public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer);

これまでの拡張メソッドとは異なり、IEnumerable<Tsource> クラスに対する拡張ではなく、IOrderedEnumerable<Tsource> クラスに対する拡張となっています。IOrderedEnumerable<Tsource> クラスは並べ変えられた後のシーケンスが実装すべきインターフェースで、実は OrderBy 拡張メソッドや OrderByDescending 拡張メソッドの戻り値がこの型になっています。OrderBy 拡張メソッドや OrderByDescending 拡張メソッドについては「OrderBy 拡張メソッドで要素を昇順に並べ替える」または「OrderByDescending 拡張メソッドで要素を降順に並べ替える」を参照してください。

それでは、ThenBy 拡張メソッドのサンプコードを以下に掲載します。

Program.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using System.Linq;
  6.  
  7.     class Program
  8.     {
  9.         static void Main(string[] args)
  10.         {
  11.             var people = GetPeople();
  12.             foreach (var person in people)
  13.             {
  14.                 Console.WriteLine(person.Name + " (" + person.Age + ")");
  15.             }
  16.  
  17.             Console.WriteLine("年齢でソートします。");
  18.             var sortedPeople = people.OrderBy(x => x.Age);
  19.             foreach (var person in sortedPeople)
  20.             {
  21.                 Console.WriteLine(person.Name + " (" + person.Age + ")");
  22.             }
  23.  
  24.             Console.WriteLine("さらに氏名の長さでソートします。");
  25.             var thenbyPeople = sortedPeople.ThenBy(x => x.Name.Length);
  26.             foreach (var person in thenbyPeople)
  27.             {
  28.                 Console.WriteLine(person.Name + " (" + person.Age + ")");
  29.             }
  30.  
  31.             Console.ReadKey();
  32.         }
  33.  
  34.         /// <summary>
  35.         /// 人物コレクションの列挙子を取得します。
  36.         /// </summary>
  37.         /// <returns></returns>
  38.         static IEnumerable<Person> GetPeople()
  39.         {
  40.             yield return new Person() { Name = "鈴木 ほのか", Age = 26 };
  41.             yield return new Person() { Name = "小池 哲司", Age = 22 };
  42.             yield return new Person() { Name = "田中 淳平", Age = 26 };
  43.             yield return new Person() { Name = "中津山 亜希子", Age = 20 };
  44.             yield return new Person() { Name = "恩田 進", Age = 22 };
  45.         }
  46.     }
  47. }


サンプルコードでは、OrderBy 拡張メソッドで得られたシーケンスを用いて ThenBy 拡張メソッドを使用しています。OrderBy 拡張メソッドでは Person クラスの Age プロパティを指定しているため、年齢で並べ替えられることになります。ThenBy 拡張メソッドでは、この年齢で並べ替えられたシーケンスに対してさらに氏名の長さで並べ替えをおこなっています。あくまでも年齢で並べ替えをおこなっているため、氏名の長さで並べ替えが起こるのは同年齢の要素の間でのみとなります。例えば中津山さんは氏名の長さがこのシーケンスの中では一番長いですが、先に年齢によって並べ替えられているため、一番若い人として先頭要素のままとなっています。

並べ替えをおこなうための比較子を第 2 引数として指定できる点は OrderBy 拡張メソッドなどと同様ですので、詳しくはそちらを参照してください。