例如,我有一个类如下:
public class SampleItem
{
public string QCD { get; set; }
public string CCD { get; set; }
public string ITYPE { get; set; }
}
然后,我有一个清单:
var lstTest = new List<SampleItem>() {
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C3" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
};
我希望得到像
这样的2个群组第1组:
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C3" , ITYPE = "A"} ,
第2组:
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
所以,我只需要
lstTest.GroupBy (p=>new {p.QCD ,p.ITYPE});
但现在,如果My List的订单与下面的订单相同
var lstTest = new List<SampleItem>() {
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C3" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
};
如何获得像
这样的3个群组第1组:
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
第2组:
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C3" , ITYPE = "A"} ,
第3组:
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
按LINQ
?
谢谢你的任何建议。
答案 0 :(得分:5)
使用GroupAdjacent
运算符,例如one listed on Eric White's blog,您可以执行以下操作:
var groupedItems = lstTest.GroupAdjacent(p => new { p.QCD, p.ITYPE });
答案 1 :(得分:4)
(现在我发帖了,我发现有一个类似的GroupAdjacent
已发布,但我会把它留在这里作为同一主体的替代实现)
使用自定义扩展方法,et voila:
static void Main() {
var lstTest = new List<SampleItem>() {
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C3" , ITYPE = "A"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
};
foreach(var group in lstTest.Split(x => new { x.QCD, x.ITYPE})) {
Console.WriteLine("{0}, {1}", group[0].QCD, group[0].ITYPE);
foreach(var item in group) {
Console.WriteLine("\t{0}", item.CCD);
}
}
}
public static IEnumerable<TSource[]> Split<TSource, TValue>(
this IEnumerable<TSource> source, Func<TSource, TValue> selector)
{
var comparer = EqualityComparer<TValue>.Default;
using(var iter = source.GetEnumerator()) {
if(iter.MoveNext()) {
List<TSource> buffer = new List<TSource>();
buffer.Add(iter.Current);
TValue groupValue = selector(iter.Current);
while(iter.MoveNext()) {
var currentItem = iter.Current;
var currentValue = selector(currentItem);
if(!comparer.Equals(groupValue, currentValue)) {
var arr = buffer.ToArray();
buffer.Clear();
yield return arr;
groupValue = currentValue;
}
buffer.Add(currentItem);
}
yield return buffer.ToArray();
}
}
}
答案 2 :(得分:0)
另一个GroupAdjacent实现:
// name your utility class how you want
public static class MyEnumerable
{
/// <summary>
/// Cuts a sequence into groups according to a specified key selector function.
/// Similar to GroupBy, but only groups adjacent items.
/// Reduces a collection a,a,B,B,B,a,p,p,p,p to (a,a),(B,B,B),(a),(p,p,p,p).
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <typeparam name="TKey">The type of the key returned by keySelector.</typeparam>
/// <param name="source">An <see cref="System.Collections.Generic.IEnumerable"/> whose elements to group.</param>
/// <param name="keySelector"> A function to extract the key for each element.</param>
/// <returns>
/// An IEnumerable<IGrouping<TKey, TSource>> in C# or
/// IEnumerable(Of IGrouping(Of TKey, TSource)) in Visual Basic
/// where each <see cref="System.Linq.IGrouping"/> 2 object contains a sequence of objects and a key.
/// </returns>
public static IEnumerable<IGrouping<TKey, TSource>> GroupAdjacentBy<TKey, TSource>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
using (var en = source.GetEnumerator())
{
if (!en.MoveNext()) yield break;
var key = keySelector(en.Current);
var elements = new List<TSource> { en.Current };
while (en.MoveNext())
{
var nextKey = keySelector(en.Current);
if (!Equals(nextKey, key))
{
yield return new Grouping<TKey, TSource>(key, elements);
key = nextKey;
elements = new List<TSource>();
}
elements.Add(en.Current);
}
yield return new Grouping<TKey, TSource>(key, elements);
}
}
这也可以像
一样使用new[]{"one","seven","force","wow","bye"}.GroupAdjecent(s=>s.Length)
返回包含
的IGroupings