【发布时间】:2014-10-23 11:38:45
【问题描述】:
我有一个我自己的类“Vertrag”(“Contract”)的实例列表,需要对它们进行分组。
一个简单的 GroupBy 正是我需要的:按最后四个字段分组,结果是一个 IEnumerable
在标记为 ... 的地方没有给出类型定义。所以这似乎是一个匿名类型?
现在我有一个进一步的要求:确保有一个最大值。每组三个元素。开始新的组(仍然是相同的键!),直到全部分配完毕。我在 StackOverflow 中也找到了一个解决方案,LINQ 有点复杂但工作正常。只是返回类型有点复杂。
我更愿意将这个复杂的结构转换回简单的 IGrouping 形式,以便它可以与现有代码一起使用。
我几乎可以使用它,或者至少简化为一个与简单的 GroupBy 一样易于使用的版本,但并不完全相同。 有没有办法自己创建这个匿名类型的IGrouping,这样就不需要按照原来的分组修改代码了?
密钥会多次出现相同的情况,这与 GroupBy 的意思完全相反。所以我不确定手工制作的 IGrouping 是否会允许它存在。
这是一个有效的 LINQPad 示例(带有类型定义):
void Main()
{
List<Vertrag> verträge = new List<Vertrag>();
verträge.Add(new Vertrag("a1","b1","c","d","e"));
verträge.Add(new Vertrag("a2","b1","c","d","e"));
verträge.Add(new Vertrag("a3","b1","c","d","e"));
verträge.Add(new Vertrag("a4","b1","c","d","e"));
verträge.Add(new Vertrag("a5","b1","c","d","e"));
verträge.Add(new Vertrag("a6","b1","c","d","e"));
verträge.Add(new Vertrag("a7","b1","c","d","e"));
verträge.Add(new Vertrag("a1","b2","c","d","e"));
verträge.Add(new Vertrag("a2","b2","c","d","e"));
verträge.Add(new Vertrag("a3","b2","c","d","e"));
verträge.Add(new Vertrag("a4","b2","c","d","e"));
// Very easy first group
var verträgeGruppiert = verträge
.GroupBy(v => new { v.Beginn, v.Ende, v.Vorlage, v.Ware });
verträgeGruppiert.Dump();
// Far more complex grouping
var maxInGroup = 3;
var verträgeGruppiertMax = verträge
.GroupBy(v => new {v.Beginn, v.Ende, v.Vorlage, v.Ware})
.Select(g => new
{
Key = g.Key,
Teile = g.Select((v,i) => new {Value = v, Index = i})
.GroupBy(item => item.Index / maxInGroup)
});
verträgeGruppiertMax.Dump();
// Transform back into simpler style
// SelectMany used instead select, see comment in question
var vereinfacht = verträgeGruppiertMax
.SelectMany(vgm => vgm.Teile
.Select(t => new
{
vgm.Key,
a = t.Select(x => x.Value.ID)
}));
vereinfacht.Dump();
}
public class Vertrag
{
public Vertrag( // Constructor
string id,
string beginn,
string ende,
string vorlage,
string ware)
{
ID = id;
Beginn = beginn;
Ende = ende;
Vorlage = vorlage;
Ware = ware;
}
// Fields
public string ID { get; private set; }
public string Beginn { get; private set; }
public string Ende { get; private set; }
public string Vorlage { get; private set; }
public string Ware { get; private set; }
}
【问题讨论】:
-
如果外部 .Select 是 .SelectMany,则最终的转换效果会更好。而不是 IEnum
> 这给出了 IEnum<...>,更接近原始 GroupBy 结果 -
我认为做你想做的唯一方法是修改键以包含 (index/3) 值,但我不确定你的代码的其余部分是如何使用结果的这个查询。无论哪种方式,您很可能都必须更改代码才能使用新结果。