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

使用LINQ进行字母数字排序分享

时间:2023-04-10 20:39:10 C#

C#学习教程:使用LINQ进行字母数字排序string[]partNumbers=newstring[]{"ABC10","ABC1","ABC2","ABC11","ABC10","AB1","AB2","Ab11"};我正在尝试按如下方式使用LINQ对上述数组进行排序,但没有得到预期的结果。varresult=partNumbers.OrderBy(x=>x);实际结果:AB1AB11AB2ABC1ABC10ABC10ABC11ABC2预期结果AB1AB2AB11..这是因为字符串的默认排序是标准字母数字字典(字典)排序,ABC11将排在ABC2之前,因为排序总是从左到右发生.为了得到你想要的,你需要在orderby子句中填充数字部分,例如:varresult=partNumbers.OrderBy(x=>PadNumbers(x));其中PadNumbers可以定义为:publicstaticstringPadNumbers(stringinput){returnRegex.Replace(input,"[0-9]+",match=>match.Value.PadLeft(10,'0'));这将替换任何填充零的数字(或数字),以便OrderBy看到:ABC0000000010ABC0000000001...AB0000000011填充仅发生在用于比较的键上。原始字符串(没有填充)将保留在结果中。请注意,此方法假定输入中的最大位数。可以在DaveKoelle的网站上找到“正常工作”字母数字排序方法的正确实现。C#版本在这里。公共类AlphanumComparatorFast:IComparer{ListGetList(strings1){ListSB1=newList();字符串st1、st2、st3;st1="";boolflag=char.IsDigit(s1[0]);foreach(charcins1){if(flag!=char.IsDigit(c)||c=='''){if(st1!="")SB1.Add(st1);st1="";flag=char.IsDigit(c);}如果(char.IsDigit(c)){st1+=c;}如果(char.IsLetter(c)){st1+=c;}}SB1.Add(st1);返回SB1;}publicintCompare(objectx,objecty){strings1=xasstring;如果(s1==null){返回0;}字符串s2=y作为字符串;如果(s2==null){返回0;}如果(s1==s2){返回0;}intlen1=s1.Length;intlen2=s2.长度;int标记1=0;int标记2=0;//使用两个标记遍历两个字符串。列表str1=GetList(s1);列表str2=GetList(s2);while(str1.Count!=str2.Count){如果(str1.Countstr2[i].ToString().Length)结果=-1;否则结果=0;}else{intst1ZeroCount=str1[i].ToString().Trim().Length-str1[i].ToString().TrimStart(newchar[]{'0'}).长度;intst2ZeroCount=str2[i].ToString().Trim().Length-str2[i].ToString().TrimStart(newchar[]{'0'}).长度;如果(st1ZeroCount>st2ZeroCount)结果=-1;elseif(st1ZeroCount使用此类:Listmarks=newList();marks.Add("M'00Z1");marks.Add("M'0A27");marks.Add("M'00Z0");marks.Add("0000A27");marks.Add("100Z0");string[]Markings=marks.ToArray();Array.Sort(Markings,newAlphanumComparatorFast());如果你想使用LINQ和自定义比较器(例如DaveKoelle的自定义比较器)按特定属性对对象列表进行排序,您可以这样做:...items=items.OrderBy(x=>x.property,newAlphanumComparator()).ToList();...您还必须将Dave的类更改为inheritSystem.Collections.Generic.IComparer而不是基础IComparer,以便类签名变为:...publicclassAlphanumComparator:System.Collections.Generic.IComparer{...就个人而言,我更喜欢JamesMcCormack的实现,因为它实现了IDisposable,尽管我的基准测试显示它稍慢您可以使用PInvoke获得快速且良好的结果:publicintCompare(stringx,stringy)=>StrCmpLogicalW(x,y);您可以像上面的答案一样使用AlphanumComparatorFast。您可以PInvoke到StrCmpLogicalW(windows函数)来执行此操作。请参阅此处:C#中的自然排序顺序它看起来像是按字典顺序排序,包括小写字母和大写字母。您可以尝试在该lambda中使用一些自定义表达式来执行此操作。在.NET中没有自然的方法来执行此操作,但请查看有关自然排序的博客文章您可以将其放在扩展方法中并使用它代替OrderBy因为开头的字符数是可变的,所以Regular表达式帮助:varre=newRegex(@"d+$");//查找字符串末尾的连续数字varresult=partNumbers.OrderBy(x=>int.Parse(re.Match(x).Value));如果有固定数量的前缀字符,则可以使用Substring方法从相关字符开始提取://将字符串解析为从第5个字符开始的数字varresult=partNumbers.OrderBy(x=>int.解析(x.子串(4)));如果数字可能包含小数分隔符或千位分隔符,正则表达式也需要允许这些字符:varre=newRegex(@"[d,]*.?d+$");varresult=partNumbers.OrderBy(x=>double.Parse(x.Substring(4)));如果正则表达式返回的Substring或者Substring字符串可能是int.Parse/double.Parse无法解析,使用相关的TryParse变量:varre=newRegex(@"d+$");//查找字符串末尾的连续数字varresult=partNumbers.OrderBy(x=>{int?parsed=null;if(int.TryParse(re.Match(x).Value,outvartemp)){parsed=temp;}returnparsed;});我不知道如何在LINQ中执行此操作,但也许你喜欢这样:Array.Sort(partNumbers,newAlphanumComparatorFast());//显示结果以上是C#学习教程:AlphanumericsortingusingLINQ分享的所有内容,如果对大家有用,需要详细了解C#学习教程,希望大家多加关注—foreach(stringh在partNumbers){Console.WriteLine(h);}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: