如何获得linq中最高和最低价格项目的总和

时间:2012-04-15 19:41:52

标签: c# linq

我试图写的实际查询比标题所暗示的要复杂一些。我有一个类似的订单列表:List<Order>,订单如下:

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语句中执行此操作。

3 个答案:

答案 0 :(得分: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 - 并且您可能想要创建自定义value类型用于保存四个值,以避免创建超出需要的对象。那可能有点矫枉过正,但你确实说过你希望它尽可能高效......

答案 1 :(得分:0)

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

类似于LOWEST。

遗憾的是,Linq2SQL不会将其转换为高效查询。它将在一个查询中执行,但每次Max操作将扫描一次数据(在您的情况下,两次:HIGHEST和LOWEST)。在原始SQL中,您可以通过数据进行一次传递。

答案 2 :(得分: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;