2

OrderBy と ThenBy を使用した linq クエリ (データベース関連ではない) があります。

var sortedList = unsortedList
                .OrderBy(foo => foo.Bar) //this property access is relatively fast
                .ThenBy(foo => foo.GetCurrentValue()) //this method execution is slow

取得foo.Barは高速ですが、実行foo.GetCurrentValue()は非常に遅いです。戻り値は、一部のメンバーが等しい Bar 値を持っている場合にのみ問題になります。これはめったに発生しませんが、発生した場合に備えて考慮することが重要です。バーの値が等しい場合にタイブレークが必要な場合にのみ、ThenBy 句を実行することを選択することは可能ですか? (つまり、foo.Bar 値が一意の場合は実行されません)。

また、実際には Bar も少し遅いため、同じオブジェクトに対して 2 回呼び出さないことをお勧めします。

4

5 に答える 5

5

データベースを使用しておらず、並べ替えを厳密に制御する必要があるため、必要なものだけにアクセスし、不要な評価を実行しないカスタムIComparerで単一のOrderByを使用できます。

于 2012-05-22T03:43:45.837 に答える
4

これは少し不器用ですが、改善できると確信しています.1つのlinqステートメントでは実行できないかもしれませんが、うまくいくはずです:

var sortedList2 = unsortedList
                .OrderBy(foo => foo.Bar)
                .GroupBy(foo => foo.Bar);

            var result = new List<Foo>();
            foreach (var s in sortedList2)
            {
                if (s.Count() > 1)
                {
                    var ordered = s
                        .OrderBy(el => el.GetCurrentValue());
                    result.AddRange(ordered);
                }
                else
                {
                    result.AddRange(s);
                }
            }

更新:
それが改善であるかどうかは議論できますが、少なくともより簡潔に見えます:

var list3 = (from s in sortedList2
             let x = s.Count()
             select x == 1 
                    ? s.Select(el => el) 
                    : s.OrderBy(el => el.GetCurrentValue()))
             .SelectMany(n => n);

更新 2:

Skip(1).Any()代わりに使用できますCount()-これは、私が推測するシーケンス全体の列挙を回避するはずです。

于 2012-05-22T07:13:58.020 に答える
1
var query = unsortedList
  .GroupBy(foo => foo.Bar)
  .OrderBy(g => g.Key)
  .SelectMany(g => g.Skip(1).Any() ? g.OrderBy(foo => foo.GetCurrentValue()) : g);

これには、戻らないという明らかな欠点がありますIOrderedEnumerable<Foo>

于 2012-05-23T14:13:06.480 に答える
0

これを試してみてください

var sortedList = unsortedList.OrderBy(foo => foo.Bar);

if(some_Condition)
{ 
   sortedList = sortedList.OrderBy(foo => foo.GetCurrentValue()); 
}
于 2012-05-22T03:43:18.633 に答える
0

Joanna Turban のソリューションを変更し、次の拡張メソッドを開発しました。

public static IEnumerable<TSource> OrderByThenBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> orderBy, Func<TSource, TKey> thenBy)
{
    var sorted = source
        .Select(s => new Tuple<TSource, TKey>(s, orderBy(s)))
        .OrderBy(s => s.Item2)
        .GroupBy(s => s.Item2);

    var result = new List<TSource>();
    foreach (var s in sorted)
    {
        if (s.Count() > 1)
            result.AddRange(s.Select(p => p.Item1).OrderBy(thenBy));
        else
            result.Add(s.First().Item1);
    }
    return result;
}
于 2013-02-08T01:49:00.143 に答える