2011-06-13 6 views
5

インプレースリストにLINQのORDERBYを変換し、私はその後、結果にToList()をやって、オブジェクトにLINQを使用して、リストを並べ替えています:現在のソート

var SortedPossibleMoveLocations = (from PML in PossibleMoveLocations 
            orderby Randomiser.Next() 
            orderby IsSameType(PML) ? (_Owner[PML] as TileFlowing).UnitsWithin : 0 
            orderby PossibleMoveLocationOrdering(PML) 
            select PML).ToList(); 

私はインプレースの並べ替えを行うには、これを変換したい、私はList<T>.Sort()メソッドを使用して推測します。しかし、もし私がただ1つのことで注文していたのであれば、私はPossibleMoveLocationOrderingintを返します)、IsSameType(PML) ? (_Owner[PML] as TileFlowing).UnitsWithin : 0、、次にRandomiser.Next()(これはランダムint )私はこれを行う方法を知らない。

質問:上記のLINQクエリの暗黙的な並べ替えを行うには、どのように比較関数を書くか(より良い方法がありますか)。最も一般的

+2

複数のorderbyはほとんど常に*間違っています - それは 'ThenBy'を追加しないので、実際にソートの優先順位を逆転します。それは複数の式を持つ単一のorderbyでなければなりません –

+0

私はorderby x、y、zの反対を注文することを理解します。 (私は単一のorderby構文について知る前にこれを書いていましたが)。だからこそ、コードの下のテキストでは、何が起こっているのかを明確にしています。しかし、情報をありがとう。 –

答えて

10

最初に、3つのorderby句を指定することは悪い考えです。代わりにカンマ区切りを使用して複数の順序を指定してください。

私はまた、Randomiser.Next()を発注に使用するという考えに熱心ではありませんが、それは脇にあります。

あなたのLINQクエリ(まだ一瞬でRandomiserで)次のようになります。

var query = (from PML in PossibleMoveLocations 
      orderby PossibleMoveLocationOrdering(PML), 
        IsSameType(PML) ? (_Owner[PML] as TileFlowing).UnitsWithin : 0, 
        Randomiser.Next() 
      select PML).ToList(); 

個人的に私はちょうどこのため、ドット表記を使用したい:

var query = PossibleMoveLocations 
       .OrderBy(pml => PossibleMoveLocationOrdering(PML)) 
       .ThenBy(pml => IsSameType(pml) ? 
            (_Owner[pml] as TileFlowing).UnitsWithin : 0) 
       .ThenBy(pml => Randomiser.Next()) 
       .ToList(); 

ソートするには代わりに、複数のものをテストできるComparison<T>またはIComparer<T>と、プロパティを使用して比較者を作成する実装が基本的に必要です。あなたは(マルクのコードごとに)手動でそれを行うことができますが、それが起こるように、私はMiscUtilに、いくつかのヘルパークラスと拡張メソッドを持っている:ここRandomizerを使用するよう間違い悪い考えであることを

var comparer = ProjectionComparer<PossibleMove> 
        .Create(pml => PossibleMoveLocationOrdering(PML)); 
        .ThenBy(pml => IsSameType(pml) ? ...) 
        .ThenBy(...); 

list.Sort(comparer); 

注意各比較(最初の部分が等しいオブジェクトの場合)で呼び出されます... x < y < xのような矛盾した比較につながります。

+0

最終的な(他のすべての順序で値が等しい)大文字の乱数で注文するのは何でしょうか? –

+0

また、複数のorderbyを使い分けているのは、読みやすさが理由であるか、別の理由があるのでしょうか? –

+0

@George:基本的に、その場合は一貫した注文はありません。 2つのオブジェクトを一貫して区別できない場合は、比較するときに0を返さないのはなぜですか? –

6

list.Sort((x,y) => { 
    int result = /* first comparison, for example 
        string.Compare(x.Name, y.Name) */ 
    if (result == 0) result = /* second comparison, 
           for example x.Id.CompareTo(y.Id) */ 
    ... 
    if (result == 0) result = /* final comparison */ 
    return result; 
}); 

または類似の(おそらく比較演算クラスで、それは非自明である場合)。

関連する問題