LINQ和分组,但也得到行项值分组前

  • 本文关键字:LINQ c# linq
  • 更新时间 :
  • 英文 :


我有一个汽车类型的列表,如下List<Car> cars:

<表类> ID 颜色 使 模型 公里 tbody><<tr>1红宝马M310002红宝马318 i10003黑色奔驰C20010004黑色奔驰E20010005白色奔驰CLA20010006白色奔驰E20010007白色奔驰E20020008白色奔驰E2003000

分组在概念上是列表的列表。您似乎希望将其解压缩为一个简单的列表,并在此过程中使用子列表的聚合。将列表的列表转换为列表的过程是SelectMany

var carDetails = cars
.GroupBy(c => new
{
c.Colour,
c.Make,
c.Model
})
.SelectMany(g => g, (subList, aCarInTheSublist) => new CarDetail
{
Colour= aCarInTheSublist.Colour,
Make= aCarInTheSublist.Make,
Model= aCarInTheSublist.Model,                    
WeightedKm = (double)aCarInTheSublist.Km  / subList.Sum(aCar => aCar.Km ) //cast to double because int math 1000/3000 = 0
}).ToList();

用Select攻击它会遇到麻烦,因为你选择的是组,即外列表。下面这个简单的例子:

A, 1
A, 2
A, 3
B, 1

如果你按字母分组,你的输出只有2行:

A -> {A,1} {A,2} {A,3}
B -> {B,1}

所以你会努力回到你想要的4行,因为Select只运行两次。

SelectMany将访问组中的每个条目(即两个组A和B, A组有3个子条目)并访问每个子条目,因此对于A组(单个组有3个成员,A1, A2和A3),它将导致投射出3个元素。至关重要的是,当它访问A1, A2和A3时,对A组的整体访问仍然是可用的,所以你可以将其中所有的km求和

这可能不是很有效,因为我们反复总结组,但LINQ并不总是赢得效率竞赛:)

你可以考虑用CPU时间来交换内存,通过把总和放入字典来记住总和:

var d = cars
.GroupBy(c => new
{
c.Colour,
c.Make,
c.Model
})
.ToDictionary(g=>g.Key, g=>g.Sum(c=>c.Km));
var result = cars
.Select(c => new CarDetail
{
Colour= c.Colour,
Make= c.Make,
Model= c.Model,                    
WeightedKm = (double)c.Km  / d[new{c.Colour,c.Make,c.Model}]
}).ToList();
边注:当使用LINQ时,尽量保持别名代表列表条目。cars是一个汽车列表,所以Select(c =>有助于保持它是一辆汽车。

AGroupBy(c=>...).Select(g=>提醒您正在对汽车进行分组,然后Select对分组进行操作。组中的每一项都是一个Car,因此您可能希望Select(gc=>表示"group of cars",而Select(gc=> gc.Select(c=>表示第二次选择操作的是一个可枚举的Car,因此返回到c有助于澄清

最新更新