当前位置: 首页 > 编程语言 > C#

Linqorderby,从特定数开始,然后返回最低份额

时间:2023-04-10 16:18:01 C#

Linqorderby,从特定数开始,然后返回最低,当达到最高数时,返回最低点,继续递增。例如,对于序列(1,2,3,4,5,6),如果4是一个特定的数字,序列将变为(4,5,6,1,2,3)。这可能与linq&c#吗?列表list=newList(){1,2,3,4,5,6};整数=4;varnewList=list.SkipWhile(x=>x!=num).Concat(list.TakeWhile(x=>x!=num)).ToList();int具体=4;varnumbers=Enumerable.Range(1,9);varresult=numbers.OrderBy(n=>Tuple.Create(n我使用了一个小技巧,使用Tuple作为比较器,因为false。另一种选择是:varresult=numbers.OrderBy(n=>nn).ToList();基准测试后编辑我找到了第二个解决方案。OrderBy.ThenBy比Tuple解决方案快得多。我相信这是因为FCL使用Comparer.Default作为比较器,这需要时间来构建。OrderBy()本身非常强大,并且扩展它的范围,有ThenBy()所以,在我看来,更多的ThenBy()方法是:varlist=new[]{1,2,3,4,5,6};varpivot=4;varorder=list.OrderBy(x=>x==pivot?0:1).ThenBy(y=>y您可以实现自定义IComparer。像这样(注意代码未经测试!):Listlist=newList(){1,2,3,4,5,6};list.OrderBy(n=>n,newIntComparer(4));公共类IntComparer:IComparer{int开始;publicIntComparer(intstart){this.start=start;}//按高度、长度和宽度进行比较。publicintCompare(intx,inty){if(x>=start&&y=start)//Y大于Xreturn-1;否则如果(x==y)返回0;否则返回x>y?1:-1;}}列表list=newList(){1,2,3,4,5,6};项目=4;varindex=input.IndexOf(item);varfirstList=input.Take(index);返回input.Except(firstList).Concat(firstList).ToList();对于一般情况,以下是应该为任何类自定义的IComparer。公共类StartWithComparer:IComparer{privateTstartWith;私人IComparerbaseComparer=Comparer.Default;publicStartWithComparer(TstartWith,IComparerbaseComparer=null){this.startWith=startWith;if(baseComparer!=null)this.baseComparer=baseComparer;}publicintCompare(Tx,Ty){intxToS=baseComparer.Compare(x,startWith);intyToS=baseComparer.Compare(y,startWith);如果(xToS>=0&&yToS=0)返回1;否则返回baseComparer.Compare(x,y);}}称为new[]{1,2,3,4,5,6}.OrderBy(i=>i,newStartWithComparer(4))Listlist=newList(){1,2,3,4,5,6};整数=4;intmax=list.Max();varresult=list.OrderBy(i=>i>=number?i:max+i);我将在这里提出一个异端解决方案,因为它根本不使用标准的LINQ运算符:IEnumerableGetSequence(IListinput,intindex){for(vari=index;我认为这清楚地表明了意图。我不认为您必须使用标准LINQ查询运算符(Skip、Take、Concat的组合)进行的奇怪扭曲是可读或可维护的。我认为只是为了它,在这种情况下使用它们是一种滥用。循环很好。您可以使用(或滥用,我承认)一个简单的减法来完成此操作:varseq=Enumerable.Range(0,10);诠释n=4;intm=seq.Max()+1;//或者像1000这样的幻数,谢谢RB。varordered=seq.OrderBy(x=>x>=n?x-m:x);foreach(intiinordered)Console.WriteLine(i);此外,如果数字变大,请注意整数溢出。对于简单的情况,它可能没问题。这是一个更好的解决方案(受其他答案启发):varseq=Enumerable.Range(0,10);诠释n=4;varordered=seq.Where(x=>x>=n).OrderBy(x=>x).Concat(seq.Where(x=>xx));foreach(intiinordered)Console.WriteLine(i);它对每个序列进行排序。在连接它们之前。T_12在评论中询问他们是否按升序排序。如果是这种情况,请使用LB的解决方案而不是我的解决方案,因为OrderBy将努力至少为O(nlogn)而不是O(n)(线性)。将序列移动到给定项目开头的扩展方法。这也只会通过原始序列一次,这可能重要也可能无关紧要。这也假设序列已经按照您想要的方式排序,除了移位。publicstaticIEnumerableShift(thisIEnumerablesubject,TshouldBeFirst){returnsubject.Shift(shouldBeFirst,EqualityComparer.Default);}publicstaticIEnumerableShift(thisIEnumerablesubject,TshouldBeFirst,IEqualityComparercomparer){varfound=false;变种队列=新队列();foreach(variteminsubject){if(!found)found=comparer.Equals(item,shouldBeFirst);}如果(找到)产生退货项目;否则队列。排队(项目);}while(queue.Count>0)yieldreturnqueue.Dequeue();}使用方法varlist=newList(){1,2,3,4,5,6};foreach(variinlist.Shift(4))Console.WriteLine(i);打印456123如果您的数据是List则可以:varsequence=new[]{1,2,3,4,5,6}.ToList();列表结果;开始=4;intindex=sequence.IndexOf(start);如果(索引==0)结果=序列;elseif(index>-1){result=sequence.GetRange(index,sequence.Count-index);varsecondPart=sequence.GetRange(0,sequence.Count-索引);结果.AddRange(secondPart);}这不是真正的排序,而是创建一个新的列表上面是C#学习教程:Linqorderby,从具体的数字开始,然后返回最低份额的全部内容,如果对大家有用需要了解一下更多关于C#学习教程,希望大家多多关注---本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: