2012-04-15 67 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

相关问题