【问题标题】:Implementing custom IComparer with string使用字符串实现自定义 IComparer
【发布时间】:2018-02-15 17:50:12
【问题描述】:

例如,我在 c# 中有一个字符串集合;

var example = new string[]{"c", "b", "a", "d"};

然后我对此进行排序,但我的 IComparer 方法不起作用,并且看起来无限循环。

基本上我需要先"b",然后是"c",然后我才不管其他的顺序。

这可以使用 IComparer<string>Compare(string x, string y) 方法吗?

编辑:代码

    public int Compare(string x, string y)
    {
        var sOrder = new string[] { "b", "c" };
        int index_x = -1;
        int index_y = -1;

        for (int i = 0; i < sOrder.Length;i++)
        {
            if (sOrder[i] == x)
                index_x = i;
            else if (sOrder[i] == y)
                index_y = i;
        }

        if (index_x >= 0 && index_y >= 0)
        {
            if (index_x < index_y)
            {
                return -1;
            }
            else
                return 1;
        }
        return 0;
    }

【问题讨论】:

  • 是的,有可能。我们需要查看您的代码才能告诉您它为什么不起作用...
  • 好的,这里还有很多信息缺失。没有一个字符的字符串会发生什么?您想对字符串或单个字符强制执行此排序吗?等等……

标签: c# icomparer


【解决方案1】:

这应该做你想做的:

var example = new string[]{"c", "a", "d", "b"};
var comparer = new CustomStringComparer(StringComparer.CurrentCulture);
Array.Sort(example, comparer);

...

class CustomStringComparer : IComparer<string>
{
    private readonly IComparer<string> _baseComparer;
    public CustomStringComparer(IComparer<string> baseComparer)
    {
        _baseComparer = baseComparer;
    }

    public int Compare(string x, string y)
    {
        if (_baseComparer.Compare(x, y) == 0)
            return 0;

        // "b" comes before everything else
        if (_baseComparer.Compare(x, "b") == 0)
            return -1;
        if (_baseComparer.Compare(y, "b") == 0)
            return 1;

        // "c" comes next
        if (_baseComparer.Compare(x, "c") == 0)
            return -1;
        if (_baseComparer.Compare(y, "c") == 0)
            return 1;

        return _baseComparer.Compare(x, y);
    }
}

【讨论】:

  • 这不是stackoverflow吗?你应该写if(x==y)return 0; 而不是if (_baseComparer.Compare(x, y) == 0) return 0;,这会导致递归。如果我错了,请纠正我!
  • --请忽略上面的评论^^
  • 不错的解决方案。它的性能可以稍微提高避免调用两次_baseComparer.Compare(x, y)
  • 如果字符串为空或 NULL 怎么办?
  • @prototype0815 对于当前的文化比较器,null被认为小于空字符串,空字符串小于任何非空字符串。
【解决方案2】:

一个简单的方法是用整数代替字符串。

class MyComparer : IComparer<string>
{
    public override int Compare(string x, string y)
    {
        int ix = x == "b" ? 0 : x == "c" ? 1 : 2;
        int iy = y == "b" ? 0 : y == "c" ? 1 : 2;
        return ix.CompareTo(iy);
    }
}

var example = new List<string> { "c", "b", "a", "d", "foo", "", "1", "e"};
example.Sort(new MyComparer());
foreach (var s in example)
    Console.WriteLine(s);

输出:

b
c

1
电子
一个
d
呵呵

请注意,这不是一个稳定的排序。如果您需要稳定的排序,则需要做更多的工作。

【讨论】:

  • 使用相同的比较器,Linq 的OrderBy 进行稳定排序:var ordered = example.OrderBy(s =&gt; s, new MyComparer());。但在这种情况下,你不妨直接说.OrderBy(s =&gt; s == "b" ? 0 : s == "c" ? 1 : 2)(虽然我不喜欢嵌套?: 运算符)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
相关资源
最近更新 更多