LINQ でシーケンスを降順にソートする場合、素直に OrderByDescending を使う方法と、OrderBy と Reverse を組み合わせる方法がある。
(降順ソート用 IComparer<T> を使う方法もあるが、OrderByDescending と同じなので割愛)
この 2 つの方法は、異なる結果になることがある。
理由は、OrderByDescending と OrderBy が両方とも 安定ソートであるため。
「降順の安定ソートってどっち?」と混乱するかもしれないが、OrderByDescending の実装は MSDN の記載通り同じキーを持つ要素の順序は保持される。
OrderBy も同様なので、同じキーを持つ要素については、OrderByDescending と OrderBy は同じ順序になってしまう。
つまり、両者は正反対の順序にならないため、OrderBy + Reverse は必ずしも OrderByDescending の結果と一致しない。
※並び替えキーに重複がない場合は一致する。
※要素=並び替えキーとなる場合は、順序が違っても分からないため、考慮不要
[不一致ケース]
(降順ソート用 IComparer<T> を使う方法もあるが、OrderByDescending と同じなので割愛)
この 2 つの方法は、異なる結果になることがある。
理由は、OrderByDescending と OrderBy が両方とも 安定ソートであるため。
「降順の安定ソートってどっち?」と混乱するかもしれないが、OrderByDescending の実装は MSDN の記載通り同じキーを持つ要素の順序は保持される。
OrderBy も同様なので、同じキーを持つ要素については、OrderByDescending と OrderBy は同じ順序になってしまう。
つまり、両者は正反対の順序にならないため、OrderBy + Reverse は必ずしも OrderByDescending の結果と一致しない。
※並び替えキーに重複がない場合は一致する。
※要素=並び替えキーとなる場合は、順序が違っても分からないため、考慮不要
[不一致ケース]
// インデックス付き配列を並べ替え
var data = new[]{ 'a', 'b', 'a', 'c', 'a' }.Select((V, I) => new{ V, I });
Console.WriteLine("[OrderBy]");
Console.WriteLine(string.Join(" ", data.OrderBy(v => v.V)));
Console.WriteLine("[OrderBy + Reverse]");
Console.WriteLine(string.Join(" ", data.OrderBy(v => v.V).Reverse()));
Console.WriteLine("[OrderByDescending]");
Console.WriteLine(string.Join(" ", data.OrderByDescending(v => v.V)));
[結果]
[OrderBy] { V = a, I = 0 } { V = a, I = 2 } { V = a, I = 4 } { V = b, I = 1 } { V = c, I = 3 } [OrderBy + Reverse] { V = c, I = 3 } { V = b, I = 1 } { V = a, I = 4 } { V = a, I = 2 } { V = a, I = 0 } [OrderByDescending] { V = c, I = 3 } { V = b, I = 1 } { V = a, I = 0 } { V = a, I = 2 } { V = a, I = 4 }
0 件のコメント:
コメントを投稿