如何在C#中对数组进行非标准排序?

时间:2009-08-12 17:31:51

标签: c#

的Array.Sort(测试);

出来是

_A
_B
_C
A
B
C

我反过来

C
B
A
_C
.. You know

我希望它是

_C
_B
_A
C
B
A

那我怎么能这样做?

7 个答案:

答案 0 :(得分:4)

如果内置的Array.Sort()没有按照你想要的方式排序,你可以覆盖IComparable.CompareTo方法。

请参阅此MSDN文章:如何:Sort Arrays Using Custom Criteria

答案 1 :(得分:4)

最有效和最简单的方法都是利用Comparison<T>委托在一个语句中完成所有操作。

var items = new string[] { "_A", "_B", "_C", "A", "B", "C" };
Array.Sort(items, (a, b) =>
    {
        var aUnderscore = a.StartsWith("_");
        var bUnderscore = b.StartsWith("_");
        if (!(aUnderscore ^ bUnderscore))
            return string.Compare(b, a);
        else if (aUnderscore)
            return -1;
        else if (bUnderscore)
            return +1;
        return 0;
    });

在使用lambda表达式时,虽然不是LINQ,但我相信性能不会太大,我相信。

答案 2 :(得分:2)

您可以创建一个实现IComparer(Of String)的比较器类,然后将此类的实例作为Array.Sort的第二个参数传递。

这是一个示例代码(在VB中,对不起,但C#代码类似):

Dim str = New String() {"_A", "_B", "_C", "A", "B", "C"}
Array.Sort(str, New SpecialComparer())

这是我的SpecialComparer:

Private Class SpecialComparer Implements IComparer(Of String)

    Public Function Compare(ByVal x As String, ByVal y As String) As Integer
        If x.StartsWith("_") And Not y.StartsWith("_") Then
            Return -1
        ElseIf y.StartsWith("_") And Not x.StartsWith("_") Then
            Return 1
        Else
            Return y.CompareTo(x)
        End If
    End Function

End Class

答案 3 :(得分:1)

从MSDN读取有关排序(比较)方法的this article,其中包含有关如何编写自定义排序器的代码示例。我建议复制/粘贴它并调整它直到你得到你想要的东西。

答案 4 :(得分:1)

您可以像这样实现自己的Comparer:

public class MyOwnComparer: IComparer<string>
{
    public int Compare(string x, string y)
    {
        if (x.StarsWith("_") && !y.StartsWith("_"))
            return 1;
        else if (!x.StartsWith("_") && y.StartsWith("_"))
            return -1;
        else
            return x.CompareTo(y);
    }
}

然后像这样使用它:

Array.Sort(test, new MyOwnComparer()); //sort ascending
var result = test.Reverse(); //now its descending

答案 5 :(得分:0)

可能不是最快的方式......

test = test.Where(x => x.StartsWith("_")).OrderByDescending(x => x).Concat(
       test.Where(x => !x.StartsWith("_")).OrderByDescending(x => x)).ToArray();

答案 6 :(得分:0)

根据你的标准,我只是这样做(空字符串或空字符串会引起问题):

List<string> items = new List<string>();
items.Sort();
List<string> result = items.FindAll(x => x[0] == '_');
result.AddRange(items.FindAll(x => x[0] != '_'));

如果您编写比较器来比较非“_”字符串中的“_”字符串,则不会比较所有项目的排序算法可能会遇到问题。我记得有些问题导致生成的顺序不正确,因为我写了一个做类似的比较器。

无论如何,自定义比较器:

List<string> items = new List<string>();
items.Sort(
    delegate(string a, string b)
    {
        if (a[0] == '_' && b[0] == '_')
        {
            return -a.CompareTo(b);
        }
        else if (a[0] == '_')
        {
            return 1;
        }
        else if (b[0] == '_')
        {
            return -1;
        }
        else
        {
            return a.CompareTo(b);
        }
    }
);

我也发现前者更具可读性,但是YMMV。 (注意减号以反转排序。)