我有一个我自己的类"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; }
}发布于 2014-10-23 21:53:40
只需使用自己想要的行为实现IGrouping即可。这将使您的代码变得更简单。
“应用程序”:
var elements = new List<Tuple<string, string, string, string>>();
elements.Add(Tuple.Create("a", "one", "A1", "Banana"));
elements.Add(Tuple.Create("a", "two", "B3", "Orange"));
elements.Add(Tuple.Create("a", "three", "C5", "Kiwi"));
elements.Add(Tuple.Create("a", "four", "D7", "Coconut"));
elements.Add(Tuple.Create("a", "five", "E9", "Maracuja"));
elements.Add(Tuple.Create("b", "one", "A1", "Banana"));
elements.Add(Tuple.Create("b", "two", "B3", "Orange"));
elements.Add(Tuple.Create("b", "three", "C5", "Kiwi"));
elements.Add(Tuple.Create("b", "four", "D7", "Coconut"));
elements.Add(Tuple.Create("b", "five", "E9", "Maracuja"));
var groups = elements.GroupBy(element => element.Item1);
var cuttedGroups = groups.Select(group => CuttedGroup.Create(group, 3));
foreach (var group in cuttedGroups)
{
foreach (var item in group)
{
Console.WriteLine(item);
}
Console.WriteLine();
}CuttedGroup的实现:
public static class CuttedGroup
{
public static IGrouping<TKey, TElement> Create<TKey, TElement>(IGrouping<TKey, TElement> source, int maximumElements)
{
return new CuttedGroup<TKey, TElement>(source, maximumElements);
}
}
public class CuttedGroup<TKey, TElement> : IGrouping<TKey, TElement>
{
private IGrouping<TKey, TElement> _Source;
private int _MaximumElements;
public CuttedGroup(IGrouping<TKey, TElement> source, int maximumElements)
{
// Parameter check omitted...
_Source = source;
_MaximumElements = maximumElements;
}
public TKey Key
{
get { return _Source.Key; }
}
public IEnumerator<TElement> GetEnumerator()
{
return _Source.Take(_MaximumElements).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}https://stackoverflow.com/questions/26527210
复制相似问题