前回に引き続き、今回はThenByとThenByDescendingです。
説明の方は、前回で大体行っているので、今回はサンプルのみとします。
ThenByとThenByDescendingは、複合キーにてソートする際にOrderByメソッドと
組み合わせて利用します。
ThenBy及びThenByDescendingは、単独では利用できません。
常にOrderByもしくはOrderByDescendingメソッドの結果の後に利用する必要があります。
書式は以下のようになっています。
public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>( this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector ) public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>( this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer ) public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>( this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector ) public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>( this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer )
以下サンプルです。
#region LinqSamples-23 public static class StringExtensions { public static int ToInt(this string self) { int i; if (!int.TryParse(self, out i)) { return int.MinValue; } return i; } } public class LinqSamples23 : IExecutable { class Person { public int Id { get; set; } public string Name { get; set; } public override string ToString() { return string.Format("[ID={0}, NAME={1}]", Id, Name); } } public void Execute() { var persons = new List<Person> { new Person{ Id = 1001, Name = "gsf_zero1" }, new Person{ Id = 1000, Name = "gsf_zero2" }, new Person{ Id = 111, Name = "gsf_zero3" }, new Person{ Id = 9889, Name = "gsf_zero4" }, new Person{ Id = 9889, Name = "gsf_zero5" }, new Person{ Id = 100, Name = "gsf_zero6" } }; // // 順序付け演算子には、以下のものが存在する。 // // ・OrderBy // ・OrderByDescending // ・ThenBy // ・ThenByDescending // // OrderByは昇順ソート、OrderByDescendingは降順ソートを行う。どちらも単一キーにてソートを行う。 // 複合キーにて、ソート処理を行う場合は、OrderBy及びOrderByDescendingに続いて、ThenBy及びThenByDescendingを利用する。 // // OrderBy及びOrderByDescendingメソッドは、他のLINQ標準演算子と戻り値が異なっており // IOrderedEnumerable<T> // を返す。また、ThenBy及びThenByDescendingメソッドは、引数にIOrderedEnumerable<T>を渡す必要がある。 // なので、必然的に、ThenByはOrderByの後で呼び出さないと利用出来ない。 // // LINQの並び替え処理は、安定ソート(Stable Sort)である。 // つまり、同じキーの要素がシーケンス内に複数存在した場合、並び替えた結果は元の順番を保持している。 // // // IDの昇順で、且つ、Nameの数字部分の昇順でソート. // // 以下のクエリ式と同じ事となる。 // from aPerson in persons // orderby aPerson.Id, aPerson.Name.Last().ToString().ToInt() // select aPerson // var sortByIdAndNameAsc = persons .OrderBy(aPerson => aPerson.Id) .ThenBy(aPerson => aPerson.Name.Last().ToString().ToInt()); Console.WriteLine("================= IDの昇順で、且つ、Nameの数字部分の昇順でソート. ================="); Console.WriteLine(string.Join(Environment.NewLine, sortByIdAndNameAsc)); // // IDの昇順で、且つ、Nameの数字部分の降順でソート. // // 以下のクエリ式と同じ事となる。 // from aPerson in persons // orderby aPerson.Id, aPerson.Name.Last().ToString().ToInt() descending // select aPerson // var sortByIdAndNameDesc = persons .OrderBy(aPerson => aPerson.Id) .ThenByDescending(aPerson => aPerson.Name.Last().ToString().ToInt()); Console.WriteLine("================= IDの昇順で、且つ、Nameの数字部分の降順でソート. ================="); Console.WriteLine(string.Join(Environment.NewLine, sortByIdAndNameDesc)); } } #endregion
実行すると以下のように出力されます。
================= IDの昇順で、且つ、Nameの数字部分の昇順でソート. ================= [ID=100, NAME=gsf_zero6] [ID=111, NAME=gsf_zero3] [ID=1000, NAME=gsf_zero2] [ID=1001, NAME=gsf_zero1] [ID=9889, NAME=gsf_zero4] [ID=9889, NAME=gsf_zero5] ================= IDの昇順で、且つ、Nameの数字部分の降順でソート. ================= [ID=100, NAME=gsf_zero6] [ID=111, NAME=gsf_zero3] [ID=1000, NAME=gsf_zero2] [ID=1001, NAME=gsf_zero1] [ID=9889, NAME=gsf_zero5] [ID=9889, NAME=gsf_zero4]
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ