昨天我发布了一个关于如何使用LINQ将具有多个级别的对象(使用"group")转换为平面结构的问题:
具有多个级别的对象上的LINQ GroupBy
塞德里克·比农非常友好地回答了这个问题。我想要这种转换的原因是,我可以用userData变量填充ComponentArt的Silverlight XYChart组件。然而,我刚刚发现,当以堆叠条形图格式显示时,他们的组件存在一个已知的错误。如果数据中存在空白,它将无法正确显示,因此我需要确保所有用户都具有Category的所有不同值的值。因此,在我最初的问题中,我把我想要的userData填充在哪里,我需要确保结果中也存在[User="Bob",Category="International",Spend=0.00]。
在你给我的LINQ语句之后,我使用以下代码实现了这一点:
// LINQ Statement provided by @Cedric
var userData = from spend in allSpend
from userDataPoint in
(from monthSpend in spend.Spend
from spendDetail in monthSpend.Detail
group spendDetail by spendDetail.Description into g
select new UserDataPoint
{
User = spend.UserName,
Category = g.Key,
Spend = g.Sum(t => t.Amount)
})
select userDataPoint;
// END
List<UserDataPoint> userDataNoGaps = new List<UserDataPoint>();
userDataNoGaps = userData.ToList();
foreach (string strCategory in userData.Select(c => c.Category).Distinct())
{
var existing = userData.Where(c => c.Category == strCategory).Select(c => c.User);
userDataNoGaps.AddRange(userData.Where(c => !existing.Contains(c.User)).Select(c => new UserDataPoint() { User = c.User, Category = strCategory, Spend = 0 }));
}
但当我有1000多个用户和几个类别时,我的代码相当慢。这能以某种方式被纳入Cédric提供的LINQ语句中吗?还是我最好用上面的代码来填补空白?
您可以为所有具有0
值的用户/类别准备点列表,并将其与具有union
的用户数据合并。
var userDataList = userData.ToList();
var usersList = userDataList.Select(x => x.Uder).Distinct().ToList();
var categoriesList = userDataList.Select(x => x.Category).Distinct().ToList();
// make list of UserDataPoint with 0 sums
var empty = (from user in users
from category in categoriesList
select new UserDataPoint
{
User = user,
Category = category,
Spend = 0
}).ToList();
var merged = userDataList.Union(empty)
.GroupBy(x => new { x.User, x.Category }) // here sum up empty points with real
.Select(new UserDataPoint {
User = group.Key.User,
Category = group.Key.Category,
Spend = group.Sum(y => y.Spend)
}).ToList();