我有一个字符串列表(包含房号),如下所示:
List<string> myList = new List<string> { "11", "11a", "11 a", "11-1", "11a-1" };
myList.Sort(new MyComparer());
现在,我想将列表按照以下方式排序:{"11", "11a", "11 a", "11a-1", "11-1"}
,意思是首先是没有后缀的所有数字,然后是有字母后缀的数字,最后是其他数字。因此,我将字符串分为前缀(实际数字)和后缀(数字本身后面的所有内容)。
private class MyComparer : IComparer<string>
{
protected virtual int compareHouseNumbers(string hnr1, string hnr2)
{
// ...
// split number and suffix
// ...
// housenumbers (integers) are also equal so let the suffix decide which one is greater
// the suffixes do not contain any spaces now
if (String.IsNullOrEmpty(suffix1)) return -1;
else if (String.IsNullOrEmpty(suffix2)) return 1;
// the following shell ensure that a letter comes "before" any other special char (such as "-" or "/")
if (Char.IsLetter(suffix1.FirstOrDefault()) && !Char.IsLetter(suffix2.FirstOrDefault())) return -1;
else if (!Char.IsLetter(suffix1.FirstOrDefault()) && Char.IsLetter(suffix2.FirstOrDefault())) return 1;
// if we have more complexity (compare 11a-1 with 11a-2) we use standard string-comparison
return String.Compare(suffix1, suffix2);
}
/// <inheritDoc/>
public int Compare(string lbz1, string lbz2)
{
return this.compareHouseNumbers(lbz1, lbz2);
}
}
但是我在基于这些后缀对列表进行排序时遇到了问题。我得到的列表是{"11","11 a","11a","11-1","11a-1"}。尽管交换的条目“11a”和“11 a”适合我们的目的,但我不明白为什么最后一个条目是“11a-1”而不是“11-1”。我已经通过比较进行了调试,但显然这两个成员从未直接比较,这使得很难理解到底发生了什么。我该怎么做才能使以“a”开头的后缀排在没有“a”的后缀之前?
如果有更优雅的方法来实现这一点,我会欣然接受任何改进意见。
编辑:将输入拆分为实际数字和后缀大多使用此正则表达式完成 (\d+)\s*(\S*)。这将导致整数部分(实际房屋号码)和该数字后面的字符串部分。之后,我们仅通过使用 suffix1 = suffix1.Trim(' ', '-', '/');(suffix2相应地)修剪任何非字母数字字符。话虽如此,我们实际上并没有将-1与a-1进行比较,而是将1与a-1进行比较。但是,这对结果本身没有任何影响(因为-1和1都按字典顺序小于a)。
编辑2:我消除了列表中的一些成员,以便仅剩下两个有问题的成员:“List myList = new List {“11-1”,“11a-1”}; "。更改后,排序结果如预期的那样:“{“11a-1”,“11-1”}”。
编辑3:我刚刚改变了列表中成员的顺序(将11放在列表的末尾)。现在结果也是预期的。因此,它似乎取决于列表中元素的初始顺序。非常奇怪...
11-1
将输给11a-1
,不是吗? - MakePeaceGreatAgain