2012-04-15 117 views
3

我試圖寫的實際查詢比標題暗示的要複雜一些。我有一個訂單列表像這樣的:List<Order>,順序是這樣的:如何獲得linq的價格最高和價格最低的商品的總和

public class Order 
{ 
    private StockCodes _stockCode; 
    private bool _bidSide; 
    private int _volume; 
    private decimal _price; 
} 

我需要發佈的最佳買入價和量,並給出了具體的股票代碼最好的賣出價和成交量。最佳出價定義爲bidSide爲true時的最高價格。最佳賣出價格定義爲bidSide爲false的最低價格。

例如給出下面的數據爲股票代碼「ABC」:

{ bidSide: true, volume: 25, price: 25 } 
{ bidSide: true, volume: 25, price: 25 } 
{ bidSide: true, volume: 25, price: 5 } 

{ bidSide: false, volume: 100, price: 1 } 
{ bidSide: false, volume: 50, price: 2} 
{ bidSide: false, volume: 75, price: 8 } 

最佳出價:價格25,體積50(因爲有在最高價格2項目) 最佳賣出:價格1,第100卷(因爲最低價格只有1個訂單)

最後,我需要說明何時沒有出價或出售訂單。效率是重中之重,所以如果我能夠在一個首選的linq聲明中做到這一點。

+0

這是LINQ到對象? – 2012-04-15 19:44:04

+0

(您可以在進行大量處理之前將數據分成不同的出價方*一次*這顯然會很方便...) – 2012-04-15 19:48:00

+0

對價格有任何限制?總是積極的,總是低於(說)1e20會很方便:) – 2012-04-15 19:48:47

回答

6

要有效地做到這一點,你真的只想迭代數據一次。不幸的是,這使得使用LINQ實現真的很痛苦,因爲需要做很多工作。

個人而言,我會建議你與LINQ做到這一點 - 你可以實施Aggregate它,但它不會是非常愉快的。儘管如此,簡單的foreach循環並不算太壞。喜歡的東西:

int buyVolume = -1; 
int sellVolume = -1; 
decimal buyPrice = decimal.MinValue; 
decimal sellPrice = decimal.MaxValue; 

foreach (var order in orders) 
{ 
    if (order.bidSide) 
    { 
     if (order.Price > buyPrice) 
     { 
      buyPrice = order.Price; 
      buyVolume = order.Volume; 
     } 
     else if (order.Price == buyPrice) 
     { 
      buyVolume += order.Volume; 
     } 
    } 
    else 
    { 
     if (order.Price < sellPrice) 
     { 
      sellPrice = order.Price; 
      sellVolume = order.Volume; 
     } 
     else if (order.Price == sellPrice) 
     { 
      sellVolume += order.Volume; 
     } 
    } 
} 

// Check sellVolume == -1 to verify whether we've seen any sale orders 
// Check buyVolume == -1 to verify whether we've seen any buy orders 
// Use buyPrice/buyVolume and sellPrice/sellVolume otherwise 

儘可能有效地在LINQ做這將有效地意味着將所有,在循環到一個函數的邏輯傳遞到Aggregate - 你可能會想創建一個自定義值類型保存這四個值,以避免創建比需要更多的對象。這可以是矯枉過正,但你沒有說你想讓它儘可能高效......

0
HIGHEST = orders.Max(x => x.bidSide ? x.price : (decimal?)null) ?? 0M 

與LOWEST相似。

不幸的是,Linq2SQL不會將其轉換爲有效的查詢。它將在單個查詢中執行,但數據將在每次最大操作時掃描一次(在您的情況下爲兩次:最高和最低)。在原始SQL中,您可以一次完成數據。

+0

我不認爲這是正確的。我需要最高價格的所有訂單的總量以及bidSide == true的價格。我還需要以最低價格的所有訂單數量以及bidside == false的價格之和。 – 2012-04-15 20:03:58

0

這可能做LINQ明智...

var bids = (from o in orders 
       where o.StockCode == "ABC" && o.BidSide == true 
       group o by o.Price) 
       .OrderByDescending(g => g.Key) 
       .FirstOrDefault(); 
var bidVolume = bids != null ? new Order { Price = bids.Key, Volume = bids.Sum(g => g.Volume) } : null; 

var sells = (from o in orders 
       where o.StockCode == "ABC" && o.BidSide == false 
       group o by o.Price) 
       .OrderBy(g => g.Key) 
       .FirstOrDefault(); 
var sellVolume = sells != null ? new Order { Price = sells.Key, Volume = sells.Sum(g => g.Volume) } : null; 
+0

分組然後排序並不會像* *那樣有效。 – 2012-04-15 20:10:46

+0

@JonSkeet我不質疑 - 如果它是To Objects,我看到它被提出。你完美地完成了這一部分,所以沒有什麼可以添加的,我只是想增加另一個選項。而且我猜測可能會停下來看看它是否會在特定情況下產生巨大差異。 – NSGaga 2012-04-15 20:16:03

+0

@JonSkeet此外 - 如果例如,你需要提供一個符號網格(有卷,或'拿'第一個n) - 在這種情況下,更程序化的算法會變得複雜(稍微有點)。 – NSGaga 2012-04-15 20:23:31