Comparer by string的特定排序包含和按字母顺序排列

时间:2017-02-06 15:01:34

标签: c# .net sorting

我想写Comparer,它将按字符串和字母顺序返回排序列表。 这是我的清单:

AA
AA MN
ADIDAS
ADIDAS MEN
2KC
ISANA MEN

这是我的比较器:

public class MyComparer : IComparer<string>
{
    int IComparer<string>.Compare(string x, string y)
    {
        if (x == y)
        {
            return 0;
        }
        if (x.Contains(y))
        {
            return -1;
        }
        else
        {
            return 1;
        }
    }
}

这个比较者按我的方式排序:

2KC
ADIDAS MEN
AA MEN
AA
ISANA MEN
ADIDAS

这是正确的,因为我想先检查&#34;最长的&#34;品牌(这消除了在产品中寻找品牌的错误),但通过这种排序,我想按字母顺序排序。所以我的列表看起来应该是

2KC
ADIDAS MEN
AA MEN
AA
ADIDAS
ISANA MEN

我尝试使用string.Sort(),但无法正常工作。

1 个答案:

答案 0 :(得分:1)

你有两个问题。首先,您的比较器违反了IComparer.Compare的规则。规则说如果A.CompareTo(B)返回1,则B.CompareTo(A)必须返回-1。你的比较者不这样做。例如,此代码:

string a = "abc";
string b = "def";
MyComparer comp = new MyComparer();

int rsltab = comp.Compare(a, b);  // returns 1
int rsltba = comp.Compare(b, a);  // returns 1

这显然是错误的。

无论你在比较器中做了什么,你必须确保:

  1. 如果x.Compare(y)返回-1,则y.Compare(x)返回1.
  2. 如果y.Compare(x)返回-1,则x.Compare(y)返回1.
  3. 如果x.Compare(y)返回0,则y.Compare(x)返回0.
  4. 有关比较规则的详细信息,请参阅ICompareble.CompareTo文档的“实施者说明”部分。我很惊讶在IComparer<T>的文档中没有重复这些信息。

    另一个问题是,我认为你真的不想测试x 是否包含 y。您可能想查看x 是否以 y开头。那就是:

    if (x.StartsWith(y)) return 1;
    

    但是,这也会给你一些奇怪的结果。例如,如果一个公司的名字只是另一个公司的第一个单词的前缀怎么办?例如:

    Art
    Artificial Flavor Company
    

    你真的希望人工香精公司在艺术之前进行排序,即使公司没有关系吗?

    我怀疑你真正想要的是解析字符串并查看较长字符串的第一个单词是否等于较短的字符串。因此,给定“ADIDAS”和“ADIDAS MEN”,您将解析较长的字符串以获取第一个单词,并将其与较短的字符串进行比较。这不是一个完美的解决方案,但它会比你现在拥有的更有效。