我有这堂课:
public class ItemsForMonthYear
{
public String ItemDescription { get; set; }
public String monthYr { get; set; }
public int TotalPackages { get; set; }
public Decimal TotalPurchases { get; set; }
public Decimal AveragePrice { get; set; }
public Double PercentOfTotal { get; set; }
}
...我在其中存储数据。我已经有了这个通用列表来存储其中的N个:
List<ItemsForMonthYear> itemsForMonthYearList;
...然后我从该列表中读取以填充电子表格,这非常简单:
totPackagesCell.Value2 = ifmy.TotalPackages;
totPurchasesCell.Value2 = ifmy.TotalPurchases;
avgPriceCell.Value2 = ifmy.AveragePrice;
...但是所需的下一个单元格val是基于给定monthYr的所有TotalPurchases值的计算值。所以我需要计算总数的百分比&#34;所有ItemsForMonthYear&#34;记录&#34;具有相同月份的Yr值。在SQL中,我可以这样做:
SELECT SUM(TotalPurchases) FROM ItemsForMonthYear WHERE monthYr = 'Apr 14'
...然后将该结果除以每个ItemDescription的TotalPurchases值
IOW,如果该月的所有TotalPurchases的总和&#39; 4月14日&#39;是一百万美元,以及ItemDescription&#34; Cocoa Puffs&#34;的TotalPurchases。是十万美元,我可以计算出&#34; Cocoa Puffs&#34;的百分比总和。是10%。
我可以&#34;暴力强迫它&#34;并遍历整个通用列表:
Decimal allTotalPurchases;
foreach (ItemsForMonthYear ifmy in itemsForMonthYearList)
{
if (ifmy.monthYr.Equals("Apr 14")
{
allTotalPurchases = allTotalPurchases + ifmy.TotalPurchases;
}
}
...但我认为使用LINQ可以实现更优雅/性能更友好的方式。我想这样做:
percentOfTotalCell.Value2 = GetPercentForPurchaseForMonthYearAsStr(ifmy.TotalPurchases, curMonth);
private String GetPercentForPurchaseForMonthYearAsStr(decimal totPurchasesForItemMonthYear, string totPurchasesForMonthYear)
{
percentOfTotal = // What LINQ magic goes here?
percentOfTotalStr = percentOfTotal.ToString("P", CultureInfo.InvariantCulture);
return percentOfTotalStr;
}
... arg&#34; totPurchasesForItemMonthYear &#34;将是一些价值,例如上面例子中的十万美元,以及arg&#34; totPurchasesForMonthYear &#34;将是诸如&#34; 4月14日和#34;。
之类的价值观有没有人知道这个聪明的LINQ技巧?
答案 0 :(得分:2)
您可以执行此操作来计算一个月的总购买金额:
decimal totalPurchases = itemsForMonthYearList.Where(item => item.monthYr == "Apr 14")
.Sum(item => item.TotalPurchases);
然后,您可以通过执行以下操作来计算给定项目的百分比:
decimal percentage = (itemsForMonthYearList.Single(item => item.ItemDescription == "Cocoa Puffs")
.TotalPurchases / totalPurchases) * 100;
答案 1 :(得分:2)
所需的下一个单元格val是基于给定monthYr的所有TotalPurchases值的计算值。所以我需要计算总数的百分比&#34;所有ItemsForMonthYear&#34;记录&#34;具有相同月份的Yr值。
首先,你需要获得具有相同monthYr
的那些:
var allMonthYr = itemsForMonthYearList.Where(x => x.monthYr == ifmy.monthYr);
然后它是一个简单的Sum
:
var totalPurchasesOfMonthYr = allMonthYr.Sum(x => x.TotalPurchases);
var percentOfTotal = ifmy.TotalPurchases / totalPurchasesOfMonthYr;
现在,事实证明这是非常低效的 - 因为你不必要地多次迭代这个列表。分组然后总结一次要好得多:
var groupedItemsForMonthYr = itemsForMonthYearList.ToLookup(x => x.monthYr);
var totalsForMonthYr = groupedItemsForMonthYr.ToDictionary(
x => x.Key,
x => x.Sum(x => x.TotalPurchases)
);
var percentOfTotal = ifmy.TotalPurchases / totalsForMonthYr[ifmy.monthYr];
答案 2 :(得分:2)
这是马克·布拉克特对我认为合适的解决方案的回答:
// This is code that goes outside your loop
var groupedItemsForMonthYr=itemsForMonthYearList.GroupBy(x=>x.monthYr);
var totalsForMonthYr=groupedItemsForMonthYr.ToDictionary(
x => x.Key,
x => x.Sum(y => y.TotalPurchases)
);
// This is the code that goes inside your loop
var percentOfTotal = ifmy.TotalPurchases / totalsForMonthYr[ifmy.monthYr];
以下是给出List<ItemsForMonthYear>
的答案,并在正确填写PercentOfTotal的项目中返回List<ItemsForMonthYear>
:
var items=itemsForMonthYearList.GroupBy(x=>x.monthYr)
.Select(x=>new { total=x.Sum(y=>y.TotalPurchases), i=x })
.Select(x=>x.i.Select(y=>new ItemsForMonthYear {
ItemDescription=y.ItemDescription,
monthYr=y.monthYr,
TotalPackages=y.TotalPackages,
TotalPurchases=y.TotalPurchases,
AveragePrice=y.AveragePrice,
PercentOfTotal=(double)y.TotalPurchases/(double)x.total
}))
.SelectMany(x=>x);
这是我的测试代码:
void Main()
{
var itemsForMonthYearList=new[]{
new ItemsForMonthYear { ItemDescription="A",monthYr="Aug 2014",TotalPackages=1,TotalPurchases=1,AveragePrice=1},
new ItemsForMonthYear { ItemDescription="A",monthYr="Sep 2014",TotalPackages=1,TotalPurchases=1,AveragePrice=1},
new ItemsForMonthYear { ItemDescription="A",monthYr="Sep 2014",TotalPackages=1,TotalPurchases=1,AveragePrice=1},
new ItemsForMonthYear { ItemDescription="A",monthYr="Oct 2014",TotalPackages=1,TotalPurchases=1,AveragePrice=1},
new ItemsForMonthYear { ItemDescription="A",monthYr="Oct 2014",TotalPackages=1,TotalPurchases=1,AveragePrice=1},
new ItemsForMonthYear { ItemDescription="A",monthYr="Oct 2014",TotalPackages=1,TotalPurchases=1,AveragePrice=1},
};
var items=itemsForMonthYearList.GroupBy(x=>x.monthYr)
.Select(x=>new { total=x.Sum(y=>y.TotalPurchases), i=x })
.Select(x=>x.i.Select(y=>new ItemsForMonthYear {
ItemDescription=y.ItemDescription,
monthYr=y.monthYr,
TotalPackages=y.TotalPackages,
TotalPurchases=y.TotalPurchases,
AveragePrice=y.AveragePrice,
PercentOfTotal=(double)y.TotalPurchases/(double)x.total
}))
.SelectMany(x=>x);
items.Dump();
}
public class ItemsForMonthYear
{
public String ItemDescription { get; set; }
public String monthYr { get; set; }
public int TotalPackages { get; set; }
public Decimal TotalPurchases { get; set; }
public Decimal AveragePrice { get; set; }
public Double PercentOfTotal { get; set; }
}
答案 3 :(得分:1)
decimal allTotalPurchases = itemsForMonthYearList.Where(s => s.monthYr.Equals("Apr 14")).Select(s => s.TotalPurchases).Sum();
答案 4 :(得分:0)
这段代码来自马克·布拉克特(Mark Brackett)自称“非常低效”的第一部作品,效果很好:
private String GetPercentForPurchaseForMonthYearAsStr(decimal totPurchasesForItemMonthYear, string monthToCalculate)
{
var allRecordsForMonthYr = itemsForMonthYearList.Where(x => x.monthYr == monthToCalculate);
var totalPurchasesOfMonthYr = allRecordsForMonthYr.Sum(x => x.TotalPurchases);
var percentOfTotal = totPurchasesForItemMonthYear / totalPurchasesOfMonthYr;
return percentOfTotal.ToString("P", CultureInfo.CurrentCulture);
}
由于分组代码不能为我编译,我对上面的代码感到满意。