Mech_Engineer Mech_Engineer - 1 year ago 39 Question

Sort List(of Object) by object properties

I'm trying to achieve something where the answer is already given for. But it's in

and I don't have any knowledge what-so-ever over
so I'm looking for a alternative.

I made a
which has several properties like quantity, description etc.

I add these
into a
List(of BomItem)
but now I would like to sort them according to a property. How can you sort the items based on the

Here is the link to the
solution I found.

My class code

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

How I add the

_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.
space1(loc1) = ch1
loc1 += 1
marker1 += 1

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

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

If marker2 < len2 Then
ch2 = s2(marker2)
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)
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

Answer Source

Use LINQ OrderBy:

_NewBomList.OrderBy(Function(bi) bi.ItemNumber)

and for descending:

_NewBomList.OrderByDescending(Function(bi) bi.ItemNumber)

If you want a numeric order in your string you have to convert it to an integer first:

_NewBomList.OrderBy(Function(bi) Integer.Parse(bi.ItemNumber))

To provide a custom IComparer for the OrderBy extension you have to create a class which implements IComparer(Of String) where String are your ItemNumbers to compare:

 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
         '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
           Return ix.Length.CompareTo(iy.Length) 'The number with more dots is smaller
       End If

     End Function     
  End Class

Call syntax:

Dim comparer = new ItemNumberComparer()
_NewBomList.OrderByDescending(Function(bi) bi.ItemNumber, comparer)