我有一个类似于学生坐的课程。 我的位置像B6 B7 B8 B9 B10 B11 如果我在某个类(一个oops版本)中使用FindAll,我会按此顺序获取它 一切顺利,直到我做
someclass.OrderBy(r => r.location);
之后,该位置变为B10 B11 B6 B7 B8 B9 这里出了什么问题。我没有使用orderBY更好,但任何人都可以告诉我我遇到问题的原因吗?
答案 0 :(得分:4)
您可以实现自己的自定义比较器...
class CustomCompare : IComparer<string>
{
private static readonly char[] _digits = "0123456789".ToArray();
public int Compare(string a, string b)
{
//assuming alpha start, numeric end
var alphaA = a.TrimEnd(_digits);
var alphaB = b.TrimEnd(_digits);
var alphaCompareTo = alphaA.CompareTo(alphaB);
if (alphaCompareTo != 0)
{
return alphaCompareTo;
}
var numericA = int.Parse(a.Substring(alphaA.Length));
var numericB = int.Parse(b.Substring(alphaB.Length));
return numericA.CompareTo(numericB);
}
}
......并像这样使用它......
someclass.OrderBy(r => r.location, new CustomCompare());
答案 1 :(得分:3)
这是因为字符串被比较为......好吧,字符串。 '1'
小于'6'
,因此词法比较将停止在该字符处。
听起来你想要一个natural sort而不是一个词汇排序。
答案 2 :(得分:3)
我认为你的location
属性(或字段)是一个字符串?
你可以 写一个Comparer<>
,如:
sealed class LocationComparer : Comparer<string>
{
// expect strings like "B3" or "C26"
public override int Compare(string x, string y)
{
int result = x[0].CompareTo(y[0]);
if (result != 0)
return result;
result = ushort.Parse(x.Substring(1)).CompareTo(ushort.Parse(y.Substring(1)));
return result;
}
}
像sorted = someclass.OrderBy(r => r.location, new LocationComparer());
一样使用它。
或您可以按以下方式将location
的类型更改为类:
// this class inherits the IComparable implementation of Tuple`2
sealed class Location : Tuple<char, ushort>
{
public Location(char letter, ushort number)
: base(char.ToUpper(letter), number)
{
}
public Location(string locationString)
: this(letter: locationString[0], number: ushort.Parse(locationString.Substring(1)))
{
}
public override string ToString()
{
return Item1.ToString() + Item2.ToString();
}
}
在Someclass
课程内,location
的类型为Location
。然后您的原始sorted = someclass.OrderBy(r => r.location);
将有效。
这两种解决方案都只是草图。我想你会想要添加一些健全性检查。
答案 3 :(得分:2)
按顺序排序,而不是数字排序。
'B10' < 'B6'
逐个字符地比较每个条目:
'B10'
'B6'
^
这是重要的角色(因为B是相同的)。 '6'&gt; '1'。
答案 4 :(得分:1)
orderby工作正常,请注意字符串B10出现在字符串B11之前,而字符串B11又出现在B6之前
请注意,您正在尝试订购List<string>
(或者我认为的那样),而不是List<int>
答案 5 :(得分:1)
为了在按字典顺序排序的字符串中呈现数字,需要对它们进行填充,即B01&lt; B06&lt; B10为B6> B10从左到右完成。所以,如果你知道你的上界,你的简单选择是填充,否则你将不得不重新考虑一下。
答案 6 :(得分:0)
它们总是以“X ###”的形式存在吗?如果是这样,你可以使用:
yourListObject.OrderBy(r => int.Parse(r.location.SubString(1)));
这是一个解决方法。如果情况要复杂得多,那么您还需要为新创建的Location类创建一个比较器对象。
答案 7 :(得分:0)
您需要一种自然排序算法。取this one from Ian并将其调用:
someclass.OrderBy(r => r.location, new EnumerableComparer<String>());