我有以下
List<Stock> _investments= new List<Stock>()
{
new Stock {id=msft, price =12, qty=20}
new Stock {id=msft, price =53, qty=50}
new Stock {id=csco, price =222, qty=20}
new Stock {id=fb, price 40, qty=100}
}
如果有一个符号,比如msft,我想获得总投资和收费价格。 在上面的例子中,它将是
id=msft, qty=70, price = (12*20 + 53 *50)/70 = 41.29
如何在LINQ中执行此操作? 我可以这样得到12 * 20 + 53 * 50:
var c = _investments.Where(i => i.ID == investmentName.ToUpper()).Sum(k => k.InitialPrice * k.Qty);
但如何以高效的方式包含总数量
答案 0 :(得分:2)
使用GroupBy
和Sum
:
var result = _investments
.Where(g => g.Key == "msft")
.GroupBy(i => i.id)
.Select(g => new{ id = g.Key, qty = g.Sum(i => i.qty), grp = g })
.Select(x => new
{
x.id,
x.qty,
price = Math.Round(x.grp.Sum(i => (decimal)i.price * i.qty) / x.qty, 2)
});
请注意,我已将价格转换为decimal
以防止整数除法(截断小数位)。 Math.Round
用于将结果舍入两位小数。
答案 1 :(得分:2)
最简单的方法似乎是:
var relevantInvestments = _investments
.Where(i => i.ID == investmentName.ToUpper())
.ToArray();
var totalQty = relevantInvestments.Sum(k => k.Qty);
var c = relevantInvestments.Sum(k => k.InitialPrice * k.Qty) / totalQty;
只迭代一次:
var c = _investments
.Where(i => i.ID == investmentName.ToUpper())
.Aggregate(
new { Price = 0, TotalQty = 0 },
(total, i) => new
{
Price = total.Price + i.InitialPrice * i.Qty,
TotalQty = total.TotalQty + i.Qty
},
i => i.Price / i.TotalQty);
答案 2 :(得分:2)
包含计算值的好方法可能是为此创建一个类。这样,您可以在不使用匿名类型的情况下清楚地命名和键入值,并确保计算它的工作只发生一次。为简单起见,我在这里到处使用double
,并且string
用于ID,这些ID可能与您的类型匹配,也可能不匹配(decimal
应该用于金额)。
class StockGroup
{
public List<Stock> Stocks { get; private set; }
public string Id { get; private set; }
public double TotalPrice { get; private set; }
public double AveragePrice { get; private set; }
public double Qty { get; private set; }
public StockGroup(string id, IEnumerable<Stock> stocks)
{
this.Id = id;
this.Stocks = stocks.ToList();
foreach (var stock in this.Stocks)
{
this.Qty += stock.Qty;
this.TotalPrice += stock.Price * stock.Qty;
}
this.AveragePrice = this.TotalPrice / this.Qty;
}
}
// use like
var groups =
_investments.GroupBy(x => x.Id).Select(x => new StockGroup(x.Key, x));