Vb.net 按对象属性对(对象的)列表进行排序

Vb.net 按对象属性对(对象的)列表进行排序,vb.net,list,sorting,properties,Vb.net,List,Sorting,Properties,我正在努力实现一些已经给出答案的事情。但是它在c#中,我不知道在c#中会发生什么,所以我正在寻找一个vb.net替代方案 我制作了一个名为BomItem的类,它有几个属性,如数量、描述等 我将这些BomItem添加到列表(BomItem)中,但现在我想根据属性对它们进行排序。如何根据ItemNumber属性对项目进行排序 这是我找到的c#解决方案的答案 我的班级代码 Public Class BomItem Public Property ItemNumber As String

我正在努力实现一些已经给出答案的事情。但是它在
c#
中,我不知道在
c#
中会发生什么,所以我正在寻找一个vb.net替代方案

我制作了一个名为
BomItem
类,它有几个属性,如数量、描述等

我将这些
BomItem
添加到
列表(BomItem)
中,但现在我想根据属性对它们进行排序。如何根据
ItemNumber
属性对项目进行排序

这是我找到的
c#
解决方案的答案

我的班级代码

Public Class BomItem
    Public Property ItemNumber As String
    Public Property Description As String
    Public Property Quantity As Double
    Public Property Material As String
    Public Property Certificate As String
End Class
如何添加
BomRow
对象

    _NewBomList.Add(New BomItem() With {
                    .ItemNumber = oRow.ItemNumber,
                    .Description = oPropSet.Item("Description").Value,
                    .Quantity = oRow.TotalQuantity,
                    .Material = oPropSet.Item("Material").Value,
                    .Certificate = CustomPropertySet.Item("Cert.").Value})
比较器

Public Class NaturalSort

Implements IComparer

Public Function Compare(ByVal x As Object,
            ByVal y As Object) As Integer Implements IComparer.Compare

    ' [1] Validate the arguments.
    Dim s1 As String = x
    If s1 = Nothing Then
        Return 0
    End If

    Dim s2 As String = y
    If s2 = Nothing Then
        Return 0
    End If

    Dim len1 As Integer = s1.Length
    Dim len2 As Integer = s2.Length
    Dim marker1 As Integer = 0
    Dim marker2 As Integer = 0

    ' [2] Loop over both Strings.
    While marker1 < len1 And marker2 < len2

        ' [3] Get Chars.
        Dim ch1 As Char = s1(marker1)
        Dim ch2 As Char = s2(marker2)

        Dim space1(len1) As Char
        Dim loc1 As Integer = 0
        Dim space2(len2) As Char
        Dim loc2 As Integer = 0

        ' [4] Collect digits for String one.
        Do
            space1(loc1) = ch1
            loc1 += 1
            marker1 += 1

            If marker1 < len1 Then
                ch1 = s1(marker1)
            Else
                Exit Do
            End If
        Loop While Char.IsDigit(ch1) = Char.IsDigit(space1(0))

        ' [5] Collect digits for String two.
        Do
            space2(loc2) = ch2
            loc2 += 1
            marker2 += 1

            If marker2 < len2 Then
                ch2 = s2(marker2)
            Else
                Exit Do
            End If
        Loop While Char.IsDigit(ch2) = Char.IsDigit(space2(0))

        ' [6] Convert to Strings.
        Dim str1 = New String(space1)
        Dim str2 = New String(space2)

        ' [7] Parse Strings into Integers.
        Dim result As Integer
        If Char.IsDigit(space1(0)) And Char.IsDigit(space2(0)) Then
            Dim thisNumericChunk = Integer.Parse(str1)
            Dim thatNumericChunk = Integer.Parse(str2)
            result = thisNumericChunk.CompareTo(thatNumericChunk)
        Else
            result = str1.CompareTo(str2)
        End If

        ' [8] Return result if not equal.
        If Not result = 0 Then
            Return result
        End If
    End While

    ' [9] Compare lengths.
    Return len1 - len2

End Function

End Class
公共类自然排序
实现IComparer
公共函数比较(ByVal x作为对象,
ByVal y作为对象)作为整数实现IComparer.Compare
“[1]验证参数。
尺寸s1为字符串=x
如果s1=无,则
返回0
如果结束
尺寸s2为字符串=y
如果s2=无,则
返回0
如果结束
尺寸len1为整数=s1。长度
尺寸len2为整数=s2。长度
尺寸标记1为整数=0
尺寸标记2为整数=0
“[2]在两个字符串上循环。
而marker1
使用:

对于下降:

_NewBomList.OrderByDescending(Function(bi) bi.ItemNumber)
如果要在字符串中输入数字顺序,必须先将其转换为整数:

_NewBomList.OrderBy(Function(bi) Integer.Parse(bi.ItemNumber))
编辑:
要为OrderBy扩展提供自定义的
IComparer
,您必须创建一个类,该类实现
IComparer(Of String)
其中String是要比较的
itemNumber

 Class ItemNumberComparer  
     Implements IComparer(Of String)

     Public Function Compare(String x, String y)
         Dim ix As String() = x.Split("."C)
         Dim iy As String() = y.Split("."C)

         Dim maxLen As Integer = Math.Max(ix.Length, iy.Length)
         For i As Integer = 0 To maxLen - 2
             If ix.Length >= i AndAlso iy.Length >= i Then
                If Integer.Parse(ix(i)) < Integer.Parse(iy(i)) Then
                   Return -1 'If x.i is LT y.i it must be smaller at all
                ElseIf Integer.Parse(ix(i)) > Integer.Parse(iy(i)) Then
                   Return 1 'If x.i is GT y.i it must be bigger all
                End If
             End If
         Next
         'This code is only executed if x and y differ at last number or have different ´number of dots
        If ix.Length = iy.Length Then
            Return Integer.Parse(ix(ix.Length - 1)).CompareTo(Integer.Parse(iy(iy.Length - 1))) 'Only last number differs
       Else
           Return ix.Length.CompareTo(iy.Length) 'The number with more dots is smaller
       End If

     End Function     
  End Class
使用:

对于下降:

_NewBomList.OrderByDescending(Function(bi) bi.ItemNumber)
如果要在字符串中输入数字顺序,必须先将其转换为整数:

_NewBomList.OrderBy(Function(bi) Integer.Parse(bi.ItemNumber))
编辑:
要为OrderBy扩展提供自定义的
IComparer
,您必须创建一个类,该类实现
IComparer(Of String)
其中String是要比较的
itemNumber

 Class ItemNumberComparer  
     Implements IComparer(Of String)

     Public Function Compare(String x, String y)
         Dim ix As String() = x.Split("."C)
         Dim iy As String() = y.Split("."C)

         Dim maxLen As Integer = Math.Max(ix.Length, iy.Length)
         For i As Integer = 0 To maxLen - 2
             If ix.Length >= i AndAlso iy.Length >= i Then
                If Integer.Parse(ix(i)) < Integer.Parse(iy(i)) Then
                   Return -1 'If x.i is LT y.i it must be smaller at all
                ElseIf Integer.Parse(ix(i)) > Integer.Parse(iy(i)) Then
                   Return 1 'If x.i is GT y.i it must be bigger all
                End If
             End If
         Next
         'This code is only executed if x and y differ at last number or have different ´number of dots
        If ix.Length = iy.Length Then
            Return Integer.Parse(ix(ix.Length - 1)).CompareTo(Integer.Parse(iy(iy.Length - 1))) 'Only last number differs
       Else
           Return ix.Length.CompareTo(iy.Length) 'The number with more dots is smaller
       End If

     End Function     
  End Class
此C#代码来自另一个线程:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
正如你所看到的,变化很小。您只需要知道泛型和lambda表达式的语法

不过,您应该知道,此代码不会对列表进行排序。它对列表中的项目进行排序,然后按顺序将它们添加到新列表中。这对于许多应用程序来说都很好,但是如果您在其他地方使用相同的列表,那么您将看不到新的订单。虽然有一些变体,但实际排序列表的一种方法如下:

objListOrder.Sort(Function(o1, o2) o1.OrderDate.CompareTo(o2.OrderDate))
此C#代码来自另一个线程:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
正如你所看到的,变化很小。您只需要知道泛型和lambda表达式的语法

不过,您应该知道,此代码不会对列表进行排序。它对列表中的项目进行排序,然后按顺序将它们添加到新列表中。这对于许多应用程序来说都很好,但是如果您在其他地方使用相同的列表,那么您将看不到新的订单。虽然有一些变体,但实际排序列表的一种方法如下:

objListOrder.Sort(Function(o1, o2) o1.OrderDate.CompareTo(o2.OrderDate))

另一个解决方案是实现
IComparable
()接口。此界面用于按自定义方式对对象进行排序:

Public Class BomItem
    Implements IComparable

    Public Property ItemNumber As String
    Public Property Description As String
    Public Property Quantity As Double
    Public Property Material As String
    Public Property Certificate As String

    Public Function CompareTo(obj As Object) As Integer
         Dim bom = CType(obj, BomItem)

         If Not bom Is Nothing then
             Return Me.ItemNumber.CompareTo(bom.ItemNumber)
         Else
             Throw New ArgumentException("Object is not a BomItem")
         End If
End Class
您可以按以下方式对列表进行排序:

Dim myList As New List(Of BomItem)

'Code to add your BomItems

myList.Sort()

这实际上会对列表进行排序,不会创建新的列表。

另一个解决方案是实现
IComparable
()接口。此界面用于按自定义方式对对象进行排序:

Public Class BomItem
    Implements IComparable

    Public Property ItemNumber As String
    Public Property Description As String
    Public Property Quantity As Double
    Public Property Material As String
    Public Property Certificate As String

    Public Function CompareTo(obj As Object) As Integer
         Dim bom = CType(obj, BomItem)

         If Not bom Is Nothing then
             Return Me.ItemNumber.CompareTo(bom.ItemNumber)
         Else
             Throw New ArgumentException("Object is not a BomItem")
         End If
End Class
您可以按以下方式对列表进行排序:

Dim myList As New List(Of BomItem)

'Code to add your BomItems

myList.Sort()

这实际上会对列表进行排序,但不会创建新列表。

将执行自然排序还是按ascii模型进行排序?1,2,3,4,5,6,7,8,9,10或1,10,2,20,3,30?如果您不提供任何自定义IComparer,它将按字母顺序(1,10,2,20,…)排序。如果您希望项目按文本值进行数字排序,则必须将
字符串
值转换为数字,例如
\u NewBomList.OrderBy(Function(bi)CInt(bi.ItemNumber))
。问题是,如果您的值表示数字,那么为什么要首先将它们存储在字符串属性中?我的最后一条评论并非100%正确:您可以将字符串转换为数字(例如整数),以获得相同的结果,而无需自定义IComparer。Ok fair comment;)我实现了一个替代的自然比较器,它的行数比exa少