简体   繁体   English

如何自定义字符串的排序顺序

[英]How to customize sort order of strings

I am completely new to using string arrays. 我对使用字符串数组完全不熟悉。 Consider this example: 考虑这个例子:

I have the following values in a text box: 我在文本框中有以下值:

bufallo@2000
lice@20
cell@1
rat@150
cow@10000

When I sort them, they are sorted alphabetically, as in the list above. 当我对它们进行排序时,它们按字母顺序排序,如上面的列表中所示。 However, I need them to sort in descending order using the integer value that follows the @ symbol. 但是,我需要它们使用@符号后面的整数值按降序排序。 So, for instance, I want the above list to be sorted like this: 所以,例如,我希望上面的列表像这样排序:

cow@10000
bufallo@2000
rat@150
lice@20
cell@1

I have no idea on how to arrange them in descending order like that. 我不知道如何按照这样的降序排列它们。

While doing all your logic in a single LINQ expression can prove how clever you are :) sometimes the code is just easier to read and follow if you do it in a more verbose fashion. 虽然在单个LINQ表达式中完成所有逻辑可以证明你是多么聪明:)有时代码更容易阅读和遵循,如果你以更冗长的方式做。 So, if you don't want to use LINQ, you could create your own IComparer class which contains your custom sorting algorithm: 因此,如果您不想使用LINQ,您可以创建自己的IComparer类,其中包含您的自定义排序算法:

Public Class MyComparer
    Implements IComparer(Of String)

    Public Function Compare(ByVal x As String, ByVal y As String) As Integer Implements IComparer(Of String).Compare
        Dim xParts() As String = x.Split("@"c)
        Dim yParts() As String = y.Split("@"c)

        'Get the integer value (after the @ symbol) of each parameter
        Dim xValue As Integer = 0
        Dim yValue As Integer = 0
        If xParts.Length = 2 Then
            Integer.TryParse(xParts(1), xValue)
        End If
        If yParts.Length = 2 Then
            Integer.TryParse(yParts(1), yValue)
        End If

        'Compare y-to-x instead of x-to-y because we want descending order
        Return yValue.CompareTo(xValue)
    End Function
End Class

In this example, IComparer is a standard .NET framework interface, which you are implementing in your MyComparer class. 在此示例中, IComparer是标准的.NET框架接口,您将在MyComparer类中实现该接口。 The Compare method (as defined by IComparer ) simply takes two parameters and compares them. Compare方法(由IComparer定义)只需要两个参数并进行比较。 If x is less than y (ie x comes before y in the sort-order), the method will return a negative number (eg -1). 如果x小于y (即x在排序顺序中位于y之前),则该方法将返回负数(例如-1)。 If x is greater than y , it will return a positive number (eg 1). 如果x大于y ,则返回正数(例如1)。 And if x and y are equal, then the method will return 0. 如果xy相等,则该方法将返回0。

In this case, however, since all we want to do is use the standard integer sorting, we can just call Integer.CompareTo which compares two integers and returns the negative, positive, or zero, as appropriate. 但是,在这种情况下,由于我们要做的只是使用标准整数排序,我们可以调用Integer.CompareTo来比较两个整数并根据需要返回负数,正数或零。

Then, when you call the Array.Sort method, you can give it one of your custom IComparer objects so that it uses your custom sorting algorithm instead of the default behavior: 然后,当您调用Array.Sort方法时,您可以为其提供一个自定义IComparer对象,以便它使用您的自定义排序算法而不是默认行为:

Dim arrayToSort() As String = New String() {"bufallo@2000", "lice@20", "cell@1", "rat@150", "cow@10000"}
Array.Sort(arrayToSort, New MyComparer())

The Sort method will use the IComparer object that you gave it to perform the sorting. Sort方法将使用您为其提供的IComparer对象来执行排序。 Each time it needs to compare two items in the array to see which should come first, it will call MyComparer.Compare and use the value returned by that method to determine the proper sorting. 每次需要比较数组中的两个项目以查看哪个应该首先出现时,它将调用MyComparer.Compare并使用该方法返回的值来确定正确的排序。

You can re-use the same MyComparer class everywhere in your code that you need to sort items using that same algorithm, which is another benefit over the LINQ approach. 您可以在代码中的任何位置重复使用相同的MyComparer类,使用相同的算法对项目进行排序,这是LINQ方法的另一个好处。 Implementing your own IComparer classes allows you to make all sorts of very powerful customize-able sort orders. 实现自己的IComparer类允许您制作各种非常强大的可自定义排序顺序。

You want to order by the numeric part of the string? 您想按字符串的数字部分排序吗? No need for Regex. 不需要正则表达式。

You can use String.Split and Enumerable.OrderByDescending : 您可以使用String.SplitEnumerable.OrderByDescending

Dim number As Int32 = Int32.MinValue
Dim orderedLines = From line In TextBox1.Lines
                   Let parts = line.Split("@"c)
                   Let numericPart = parts.Last()
                   Let success = Int32.TryParse(numericPart, number)
                   Select LineInfo = New With {line, number}
                   Order By LineInfo.number Descending
                   Select LineInfo.line
' if you want to reassign it to the TextBox:
TextBox1.Lines = orderedLines.ToArray()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM