C# 我如何通过Linq实现它?
例如,我有一个类,如下所示:C# 我如何通过Linq实现它?,c#,linq,C#,Linq,例如,我有一个类,如下所示: 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" , CC
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组:
new SampleItem(){ QCD = "Q1" , CCD = "C1" , ITYPE = "B"} ,
new SampleItem(){ QCD = "Q1" , CCD = "C2" , ITYPE = "B"} ,
所以,我只需要
lstTest.GroupBy (p=>new {p.QCD ,p.ITYPE});
但是现在,如果我的列表的顺序与下面的一样
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"} ,
};
第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
谢谢你的建议 使用
groupnexting
操作符,例如,可以执行以下操作:
var groupedItems = lstTest.GroupAdjacent(p => new { p.QCD, p.ITYPE });
(现在我发布了,我看到一个类似的groupnextendent
已经发布,但我将把它作为同一主体的替代实现留在这里)
使用自定义扩展方法,等等:
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();
}
}
}
static void Main(){
var lstest=新列表(){
新建SampleItem(){QCD=“Q1”,CCD=“C1”,ITYPE=“B”},
新的SampleItem(){QCD=“Q1”,CCD=“C2”,ITYPE=“B”},
新建SampleItem(){QCD=“Q1”,CCD=“C1”,ITYPE=“A”},
新建SampleItem(){QCD=“Q1”,CCD=“C2”,ITYPE=“A”},
新建SampleItem(){QCD=“Q1”,CCD=“C3”,ITYPE=“A”},
新建SampleItem(){QCD=“Q1”,CCD=“C1”,ITYPE=“B”},
新的SampleItem(){QCD=“Q1”,CCD=“C2”,ITYPE=“B”},
};
foreach(lstest.Split中的var组(x=>new{x.QCD,x.ITYPE})){
WriteLine(“{0},{1}”,组[0]。QCD,组[0]。ITYPE);
foreach(组中的var项目){
WriteLine(“\t{0}”,item.CCD);
}
}
}
公共静态可数分裂(
此IEnumerable源(函数选择器)
{
var comparer=EqualityComparer.Default;
使用(var iter=source.GetEnumerator()){
if(iter.MoveNext()){
列表缓冲区=新列表();
添加缓冲区(iter.Current);
t值组值=选择器(电流);
while(iter.MoveNext()){
var currentItem=额定电流;
var currentValue=选择器(currentItem);
如果(!comparer.Equals(groupValue,currentValue)){
var arr=buffer.ToArray();
buffer.Clear();
收益率;
组值=当前值;
}
buffer.Add(当前项);
}
产生返回缓冲区ToArray();
}
}
}
另一种实现方式:
// 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);
}
}
返回包含
- 3:1
- 5:7,强制
- 3:哇,再见
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();
}
}
}
// 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)