Linq组如何找连续同值项varschedules=newList{newItem{Id=1,Name="S"},新项目{Id=2,Name="P"},新项目{Id=3,Name="X"},新项目{Id=4,Name="X"},新项目{Id=5,名称=“P”},新项目{Id=6,名称=“P”},新项目{Id=7,名称=“P”},新项目{Id=8,名称=“S”}};在新列表中选择相同的值和相同的顺序,像这样:vargroupedAndSelectedList=newList{newList{newItem{Id=3,Name="X"},newItem{id=4,Name="X"},},newList{newItem{Id=5,Name="P"},newItem{Id=6,Name="P"},newItem{Id=7,Name="P""},}}如果item是单个itemlikenewItem{Id=3,Name="A"}我不需要获取它。Group选择列表中的所有X或P元素。但是我想知道该项目是在另一个项目之后还是之前。这可以使用linq吗?您在这里寻找的是GroupWhile方法。感谢用户LB的解决方案。转到他原来的答案UpDoothttps://stackoverflow.com/a/20469961/30155varschedules=newList{newItem{Id=1,Name="S"},newItem{Id=2,Name="P"},新项目{Id=3,Name="X"},新项目{Id=4,Name="X"},新项目{Id=5,Name="P"},新项目{Id=6、Name="P"},newItem{id=7,Name="P"},newItem{id=8,Name="S"}};varresults=schedules.GroupWhile((preceding,next)=>preceding.Name==next.Name)//分组项目,而下一个等于前一个.Where(s=>s.Count()>1)//仅包含生成的子列表具有超过1个元素的结果。.ToList();foreach(varsublistinresults){foreach(Itemiinsublist){Console.WriteLine($"{i.Name}-{i.Id}");}Console.WriteLine("");}控制台.ReadLine();您可以将实现作为扩展方法添加到所有IEnumerable。publicstaticclassExtensions{publicstaticIEnumerable>GroupWhile(thisIEnumerableseq,Funccondition){Tprev=seq.First();列表list=newList(){prev};foreach(Titeminseq.Skip(1)){if(condition(prev,item)==false){yieldreturnlist;列表=新列表();}list.Add(项目);上一个=项目;}收益返回列表;到目前为止找到的项目数达到。这可以帮助您找到连续的项目,因为count(name)-索引值对它们来说是常量:IDictionarycount=newDictionary();vargroups=schedules.Select((s,i)=>new{Item=s,Index=i}).GroupBy(p=>{varname=p.Item.Name;intcurrent;if(!count.TryGetValue(name,outcurrent)){current=0;count.Add(name,current);}count[name]=current+1;returnnew{Name=name,Order=current-p.Index};}).选择(g=>g.ToList()).Where(g=>g.Count>1).ToList();这会为您的示例生成所需的输出:{Item=Id=3Name=X,Index=2}{Item=Id=4Name=X,Index=3}-----{Item=Id=5Name=P,Index=4}{Item=Id=6Name=P,Index=5}{Item=Id=7Name=P,Index=6}演示。注意:如果Order=current-p.Index表达式看起来有点像“魔术”,请考虑删除最后的Select和Where子句,并枚举组键。@dasblinkenlight仅使用LINQ提供了答案。任何使用纯粹现有的LINQ方法的答案都可能很丑陋,性能可能很差,并且可能无法高度重用。(这不是对这个答案的批评。这是对LINQ的批评。)@eoin-campbell使用自定义LINQ方法提供了答案。但是,我认为有些功能可以改进以更紧密地匹配现有的LINQGroupBy函数,例如自定义比较器(当您需要对键进行不区分大小写的比较时)。下面的Partition方法看起来和感觉上类似于GroupBy函数,但满足连续项的要求。您可以使用此方法通过执行以下操作来实现您的目标。请注意,如果您没有连续性要求,它看起来与您编写此代码的方式完全相同,但它使用Partition而不是GroupBy。varpartitionsWithMoreThan1=schedules.Partition(o=>o.Name).Where(p=>p.Count()>1).Select(p=>p.ToList()).ToList();这是方法:staticclassEnumerableExtensions{//////根据指定的///键选择器函数将序列的元素划分为更小的集合,可选地使用指定的比较器比较键。///与GroupBy不同,此方法不会为每个键值生成一个集合。///相反,此方法为每个连续的匹配键集生成一个集合。//////的元素类型。///返回的键的类型。///要分区的元素。///为每个元素提取键的函数。///用于比较键的An。//////C#中的IEnumerable{IGrouping{TKey,TSource}}///或VisualBasic中的IEnumerable(OfIGrouping(OfTKey,TSource))///其中每个对象包含一个对象集合和一个键.///publicstaticIEnumerable>分区(t他的IEnumerablesource,FunckeySelector,IEqualityComparercomparer=null){if(comparer==null)comparer=EqualityComparer.Default;使用(varenumerator=source.GetEnumerator()){if(enumerator.MoveNext()){varitem=enumerator.Current;varpartitionKey=keySelector(item);varitemsInPartition=newList{item};varlastPartitionKey=partitionKey;while(enumerator.MoveNext()){item=enumerator.Current;partitionKey=keySelector(item);if(comparer.Equals(partitionKey,lastPartitionKey)){itemsInPartition.Add(item);}else{yieldreturnnewGrouping(lastPartitionKey,itemsInPartition);itemsInPartition=新列表{item};lastPartitionKey=分区键;}}yieldreturnnewGrouping(lastPartitionKey,itemsInPartition);}}}//很遗憾没有现成的公共实现来执行这个私有类Grouping:IGrouping{publicGrouping(TKeykey,Listitems){_items=items;钥匙=钥匙;}公共TKey密钥{得到;}publicIEnumeratorGetEnumerator(){return_items.GetEnumerator();}IEnumeratorIEnumerable.GetEnumerator(){返回_items.GetEnumerator();}私有只读列表_items;我认为这是需要的。它使用了一种扩展方法,它结合了GroupByRuns的键,GroupByRuns,它是基于GroupByWhile的组,通过测试连续的项目,它是基于ScanPair的,这是我受APL启发的ScanoperatorBody的变体,类似于Aggregate,但返回中间结果并在此过程中使用ValueTuple(Key,Value)将键与值配对。publicstaticIEnumerable>GroupByRuns(thisIEnumerablesrc,FunckeySelector,FuncresultSelector,IEqualityComparercmp=null){cmp=cmp??EqualityComparer.Default;返回src.GroupByWhile((prev,cur)=>cmp.Equals(keySelector(prev),keySelector(cur)),resultSelector);}publicstaticIEnumerable>GroupByRuns(thisIEnumerablesrc,FunckeySelector)=>src.GroupByRuns(keySelector,e=>e);publicstaticIEnumerable>GroupByRuns(thisIEnumerablesrc)=>src.GroupByRuns(e=>e,e=>e);publicstaticIEnumerable>GroupByWhile(thisIEnumerablesrc,FunctestFn,FuncresultFn)=>src.ScanPair(1,(kvp,cur)=>testFn(kvp.Value,cur)?kvp.Key:kvp.Key+1).GroupBy(kvp=>kvp.Key,kvp=>resultFn(kvp.Value));publicstaticIEnumerableScanPair(thisIEnumerablesrc,TKeyseedKey,FunccombineFn){使用(varsrce=src.GetEnumerator()){if(srce.MoveNext()){varprevkv=(seedKey,srce.Current);while(srce.MoveNext()){yieldreturnprevkv;prevkv=(combineFn(prevkv,srce.Current),srce.Current);}yieldreturnprevkv;我意识到这是很多扩展代码,但是通过使用通用的ScanPair基础,您可以构建其他专门的分组方法,例如GroupBySequential现在您只需要GroupByRuns的名称并选择具有多个成员的运行,然后转换每个运行到一个列表,整个事件到一个列表:varans=schedules.GroupByRuns(s=>s.Name)。其中(sg=>sg.Count()>1).Select(sg=>sg.ToList()).ToList();注意:对于@Aominè,他正在使用Take(2).Count()或@MichaelGunter在GroupBy子组(内部类型GroupingSkip(1).Any())之后优化Count()>1的使用的有趣尝试使用Skip(1).Any().AnySkip(1).Any()Skip(1).Any())每个实现IList和Count()方法直接从Grouping.count字段获取计数。以上就是Linq群分享的全部内容为C#学习教程:如何查找连续的相同值项。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文来自网络收藏,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:
