我有一堂课,就像学生坐的那样。我有像 B6 B7 B8 B9 B10 B11 这样的位置,如果我在某些类中使用 FindAll(一个 oops 版本),我会按照这个顺序得到它,一切都很好,直到我这样做
someclass.OrderBy(r => r.location);
在该位置变为 B10 B11 B6 B7 B8 B9 之后,这里出了什么问题。那时我不使用 orderBY 会更好,但有人能告诉我我遇到问题的原因吗?
您可以实现自己的自定义比较器...
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'
小于'6'
,因此词法比较将在该字符处停止。
听起来您想要自然排序而不是词汇排序。
我想你的location
属性(或字段)是一个字符串?
你可以写一个Comparer<>
like:
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);
就可以了。
两种解决方案都只是草图。我猜你会想要添加一些健全性检查。
Order by 使用字符串排序,而不是数字排序。
'B10' < 'B6'
逐个字符地比较每个条目:
'B10'
'B6'
^
这是重要的字符(因为 B 是相同的)。“6”>“1”。
orderby 工作正常,请注意字符串 B10 在字符串 B11 之前,而 B11 又在 B6 之前
请注意,您正在尝试订购一个List<string>
(或者这就是我的想法)而不是List<int>
为了使字符串中的数字按字典顺序呈现,它们需要被填充,即 B01 < B06 < B10 因为 B6 是 > B10,因为它是从左到右完成的。因此,如果您知道上限,您的简单选择是填充,否则您将不得不重新考虑一下。
它们总是采用“X###”的形式吗?如果是这样,您可以使用:
yourListObject.OrderBy(r => int.Parse(r.location.SubString(1)));
这是一种解决方法。如果情况要复杂得多,那么您还需要为新创建的 Location 类创建一个比较器对象。
你需要一个自然的排序算法。从伊恩那里拿走这个并称之为:
someclass.OrderBy(r => r.location, new EnumerableComparer<String>());