简体   繁体   English

如何用包含数字的字符串对列表进行排序?

[英]how to sort list with strings containing numbers?

I have a Tlist that contains addresses. 我有一个包含地址的列表。 When I sort the list, numbers in the address are considered a string, and it doesn't sort correctly. 对列表进行排序时,地址中的数字被认为是字符串,并且排序不正确。 How should I sort the list ascending? 我应该如何对列表进行升序排序?

 Dim sortme As List(Of data) = tempdata 'main list containing addresses as strings.
     sortme.Sort(Function(p1 As data, p2 As data) numorder(p1.Value).CompareTo(numorder(p2.Value)))

       Private Function numorder(ByVal str As String)
        Try
            Dim words() As String = str.Split(" "c) 'read string up to first space (for number)
            Return Convert.ToInt32(words(0))
        Catch ex As Exception
        End Try
    End Function

Example of current output: 电流输出示例:

1001 street name

103 street name

1021 street name

It should be: 它应该是:

103 street name

1001 street name

1021 street name

The idea is to write your own comparer which will firs consider the number prefix and then the string itself. 想法是编写您自己的比较器,它将首先考虑数字前缀,然后考虑字符串本身。 This comparer can be then used anywhere, for instance in LINQ OrderBy() . 然后可以在任何地方使用此比较器,例如在LINQ OrderBy() Here an example in c# see full VB.NET version below. 这里是c#中的示例,请参见下面的完整VB.NET版本。

   public class StreetComparer : IComparer<string>
    {
        public int Compare(string x, string y)
        {
            int indexOfSpaceX = x.IndexOf(' ');
            string numericalPartX = x.Substring(0, indexOfSpaceX);

            int indexOfSpaceY = y.IndexOf(' ');
            string numericalPartY = y.Substring(0, indexOfSpaceY);

            int numberX;
            int numberY;

            if(!int.TryParse(numericalPartX, out numberX) ||
                !int.TryParse(numericalPartY, out numberY))
            {
                //Some code to handle the case where number is missing
                throw new ArgumentException();
            }

            if (numberX!=numberY)
            {
                return numberX-numberY;
            }

            string textPartX = x.Substring(indexOfSpaceX + 1);
            string textPartY = x.Substring(indexOfSpaceY + 1);

            return String.Compare(textPartX, textPartY, true, CultureInfo.CurrentCulture);

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myStreets = new[] {"01 aaa", "02 bbb"};

            var result = myStreets.OrderBy(s => s, new StreetComparer());
        }
    }

Now a VB.NET version adapted exactly to your use case a List with classes sorted by property: 现在,一个VB.NET版本完全适合您的用例,其中的List具有按属性排序的类:

Public Class StreetComparer
    Implements IComparer(Of String)
    Public Function Compare(x As String, y As String) As Integer
        Dim indexOfSpaceX As Integer = x.IndexOf(" "C)
        Dim numericalPartX As String = x.Substring(0, indexOfSpaceX)

        Dim indexOfSpaceY As Integer = y.IndexOf(" "C)
        Dim numericalPartY As String = y.Substring(0, indexOfSpaceY)

        Dim numberX As Integer
        Dim numberY As Integer

        If Not Integer.TryParse(numericalPartX, numberX) OrElse Not Integer.TryParse(numericalPartY, numberY) Then
            'Some code to handle the case where number is missing
            Throw New ArgumentException()
        End If

        If numberX <> numberY Then
            Return numberX - numberY
        End If

        Dim textPartX As String = x.Substring(indexOfSpaceX + 1)
        Dim textPartY As String = x.Substring(indexOfSpaceY + 1)

        Return [String].Compare(textPartX, textPartY, True, CultureInfo.CurrentCulture)

    End Function
End Class

Public Class Person
    Public Property Value() As String
        Get
            Return m_Value
        End Get
        Set
            m_Value = Value
        End Set
    End Property
    Private m_Value As String

    Public Sub New(value__1 As String)
        Value = value__1
    End Sub
End Class

Class Program
    Private Shared Sub Main(args As String())
        Dim sortme As New List(Of Person)(New () {New Person("1001 street name"), New Person("103 street name"), New Person("1021 street name")})

        Dim result = sortme.OrderBy(Function(p) p.Value, New StreetComparer())

        For Each person As var In result
            Console.WriteLine(person.Value)
        Next
        Console.ReadKey()
    End Sub
End Class

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

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