2015-09-07 8 views
5

Linqのリストを注文するには、OrderByと電話をかけてください。ThenByに電話をかけてください。最上位の注文が不明なオーダーリスト

私は、手前でトップレベルの注文がわからない状況にあります。私は条件付きで適用されるべき注文のリストを持っています。

var list = new List<Tuple<int, string, DateTime>>(); 
list.Add(new Tuple<int, string, DateTime>(1, "B", new DateTime(2020, 1, 1))); 
list.Add(new Tuple<int, string, DateTime>(2, "A", new DateTime(2000, 1, 1))); 
list.Add(new Tuple<int, string, DateTime>(3, "C", new DateTime(1900, 1, 1))); 

var orderedList = list; 

if (sortByString) 
{ 
    orderdedList = orderedList.ThenBy(listItem => listItem.Item2); 
} 

if (sortByDateTime) 
{ 
    orderedList = orderedList.ThenBy(listItem => listItem.Item3); 
} 

orderList = orderedList.ThenBy(listItem => listItem.Item1); 

ので、リストは常に最初にアイテム2および/またはITEM3によって条件付きアイテム1が注文、およびされます。このよう

これをC#でどのように行うには? Linqのないソリューションも大歓迎です。

+1

の下のコードのようなステート・マシンを使用する必要がありますすべて**そのまま**最後の行 – Carsten

+0

'ThenBy'は' IOrderedEnumerable'でのみ利用できるので、型チェックを使うことができます。 'IOrderedEnumerable'が' ThenBy'を使用する場合 'else' OrderBy' – Jehof

+2

@Carstenそれは、Johanが' Item1'を*最後に*注文したいと思うという問題です。 – Luaan

答えて

7

ただ、これはあなたにデフォルト(非)順序付けを与え、そしてあなたは、他の多くの追加することができます

var orderedItems = list.OrderBy(_ => 1); 

使用後でご希望の注文をThenByとしてください。

EDIT:

ティムが指摘したように、これはパフォーマンスの低下を運ぶん - デフォルトLINQツーオブジェクトのプロバイダが「非を取り除くために順序を再構築するために十分にスマートではないようです - オーダリング "。あなたのリストが小さい場合、これは問題ではありませんが、無視できないほど時間がかかっている場合は、おそらくこれを難しい方法でやりたいと思っています。例えば

、あなたが

public static IEnumerable<T> AppendOrdering<T, U>(this IEnumerable<T> @this, 
                Func<T, U> selector) 
{ 
    if (@this is IOrderedEnumerable<T>) return @this.ThenBy(selector); 

    return @this.OrderBy(selector); 
} 

のようなヘルパーメソッドを使用することができ、これは、あなたがやっている正確同じではないですが、あなたは以前に発注された列挙で作業している場合を除き同じように動作します。 `と、ちょうどVAR orderedList = list.OrderBy(トン=> t.Item1)`書き込み -

+0

これは技術的には非順序ですが、同じ定数値による順序付けではありません。これはすべての項目で同じですから、最初の 'ThenBy'が使用されます。おそらくマイクロ最適化が可能ですが、大規模なコレクションでは違いがあります。なぜあなたは右から始めることができるのか疑似比較を使用するのですか?例:http://csharppad.com/gist/6d19c47c672c81dc2c52(私のPCで30秒17秒) –

+0

@TimSchmelter興味深いことに、その差は私が予想していたよりもはるかに大きいです(SQLではこれはもちろんノーオペレーションです)。私のコンピュータでは、私は16sと12sを得ています。長いリストで作業する必要がある場合は非常に高価ですが、ランタイムで100%増加するほど恐ろしいものではありません。しかし、たぶん私はあなたよりも大きなCPUキャッシュを持っているかもしれません。私は間違いなく、代わりに(実際にはそれがOPの望む方法で動作するようにした後に)、あなたの解決策に間違いなく行きます:D。これらの奇妙なデザインの決定の1つです。なぜか分かりますが、クエリの構成は必要以上に難しくなります。 – Luaan

2

使用リストの代わりにIOrderedEnumerableif ... else

IOrderedEnumerable<Tuple<int, string, DateTime>> orderedItems = null; 

if (sortByDateTime) 
    orderedItems = list.OrderBy(listItem => listItem.Item3); 
else if (sortByString) 
    orderedItems = list.OrderBy(listItem => listItem.Item2); 

orderedItems = orderedItems.ThenBy(listItem => listItem.Item1); 
list = orderedItems.ToList(); 
+0

私のソート条件は 'if {} else if {}'ではなく 'if {} if {}'であったことに注意してください。 'sortByString'と' sortByDateTime'が真であれば、2番目のorderbyは最初のものを上書きします。 –

+0

@JohanvanderSlikke:ok、明確ではありませんでした。私の答えを編集しました。しかし、 'sortByDateTime'が優先権を持っていれば' if(sortByDateTime){} else if(sortByString){} 'を使うべきです。 –

-1

は、あなたが持っているものと間違って何

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     enum State 
     { 
      One, 
      Two, 
     } 
     static void Main(string[] args) 
     { 
      State state = State.A; 

      switch (state) 
      { 
       case State.One: 
        //Order by item one 
        state = State.Two; 
        break; 
       case State.Two: 
        //Order by item two or three 
        state = State.One; 
        break; 
      } 
     } 
    } 
} 


​ 
関連する問題