2013-06-02 105 views
1

我有X和Y值A級名單:排序列表

class A 
{ 
    public int X { get; set; } 
    public int Y { get; set; } 
} 

我的列表:

List<A> MyList = GetListOfA(); 

我想排序上的一個計算值的列表屬性。例如今天美元匯率乘以X. 如果我將使用OrderBy表達式,該方法將計算x * log(x)次。

我發現了一些方法來創建內部類,包括值和變量,匿名類型列表將包括變量和計算值的列表,通過計算的關鍵字將其添加到已排序的字典中值等

乾淨簡單的語法做到最好的方法是什麼?

+1

數乘以費率不改變順序(除非稅率非正)。爲什麼不在沒有乘法的情況下按原始值排序呢? –

+0

即使這個比率是非正數,這只是反轉排序順序。 –

回答

5

如果我將使用OrderBy表達式,該方法將計算x * log(x)次。

不,它不會。在LINQ to Objects中,OrderBy將每個元素投影到其排序鍵一次,然後比較這些鍵。對於大小爲n的集合,將有n訪問屬性,然後在這些屬性值之間進行O(n log n)比較。

因此,基本上,您應該儘可能簡單地使用OrderBy來編寫代碼 - 並相信它的合理效率。

+0

謝謝!它正在工作。 – user436862

+0

絕對正確!但是,這種行爲可以更清楚地記錄下來。我想可能是原始海報混淆了LINQ'OrderBy'情況與''''''''''''''''''''可以指定'比較<>'委託的'如示例'myList.Sort((x,y)=> ExpensiveMethod(x,y,otherArgs))''。在這種情況下,如果'List <>'計數了'n',那麼委託人肯定會被調用超過'n'次。但那是一種不同的情況。 –

+0

@JeppeStigNielsen:我同意它可以更清晰地記錄下來......正如LINQ的各種情況一樣。 (有些文檔是錯誤的......) –

0

我會建議,你不改變它自己的列表,把它看作是不可變的。

保留一份此列表的副本(如所有操作發生的視圖)。

封裝在一個新的類。

我會這樣做。

2

您可以使用IComparer<T>接口:

class A 
{ 
    public int X { get; set; } 
    public int Y { get; set; } 
} 

class AComparer : IComparer<A> 
{ 
    public int Compare(A x, A y) 
    { 
     var fx = F(x); 
     var fy = F(y); 

     if (fx < fy) return -1; 
     if (fx == fy) return 0; 
     return 1; 
    } 

    double F(A a) // your calculation 
    { 
     return a.X * 1.2; 
    } 
} 

並在代碼:

var list = new List<A>(); 
// fill list 
list = list.OrderBy(a => a, new AComparer()).ToList();