To sort a class array in vb.net

一笑奈何 提交于 2019-12-10 17:49:05

问题


I have spent 2 days scouring the internet trying to find the solution to simply sort an array made up of a class of strings and integers (by just 1 of the string elements that may contain irregular characters). Please help! I have created a simplified code of what I am trying to do based on the microsoft example:

Public Class Form1
    Class car
        Public Make As String = ""
        Public Year As Integer = 0
    End Class

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim arrayOfCars() As car
        Dim arrayElement As Integer = 0

        'Exploded simplified loop to fill the array (original has 20 objects in the class
        'and the array grows depending on input to no more than a few hundred.
        ReDim arrayOfCars(0)
        arrayOfCars(0) = New car
        arrayOfCars(0).Make = "Ford"
        arrayOfCars(0).Year = 1992
        ReDim Preserve arrayOfCars(1)
        arrayOfCars(1) = New car
        arrayOfCars(1).Make = "Fiat"
        arrayOfCars(1).Year = 1988
        ReDim Preserve arrayOfCars(2)
        arrayOfCars(2) = New car
        arrayOfCars(2).Make = "Buick"
        arrayOfCars(2).Year = 1932
        ReDim Preserve arrayOfCars(3)
        arrayOfCars(3) = New car
        arrayOfCars(3).Make = "Ford"
        arrayOfCars(3).Year = 1932
        ReDim Preserve arrayOfCars(4)
        arrayOfCars(4) = New car
        arrayOfCars(4).Make = "Dodge"
        arrayOfCars(4).Year = 1999
        ReDim Preserve arrayOfCars(5)
        arrayOfCars(5) = New car
        arrayOfCars(5).Make = "Honda"
        arrayOfCars(5).Year = 1977

        'view array before sort
        For i = 0 To 5
            Debug.WriteLine(arrayOfCars(i).Make & vbTab & arrayOfCars(i).Year)
        Next
        Debug.WriteLine("*************************")

        'sort array by the string component [Make]
        'Array.Sort(arrayOfCars)
        'arrayOfCars = arrayOfCars.OrderBy(Function(car) car.Make)
        '????????????????

        'view array after sort
        For i = 0 To 5
            Debug.WriteLine(arrayOfCars(i).Make & vbTab & arrayOfCars(i).Year)
        Next
    End Sub
End Class

回答1:


If you want to sort by the Make property one out-of-the-box approach is using Array.Sort with the Comparison(Of T) overload:

Array.Sort(arrayOfCars, Function(car1 As Car, car2 as Car)
                            Return car1.Make.CompareTo(car2.Make) 
                        End Function)

Note that you should take care of cars which are Nothing or (more likely) Make-values which are Nothing. Both would cause a NullReferenceException. Therefore you could use:

Array.Sort(arrayOfCars, Function(car1 As Car, car2 As Car)
        If Object.ReferenceEquals(car1,car2)
            return 0
         Else if car1 is nothing 
            Return -1
         Else if car2 is nothing 
            Return 1
         Else
            return String.Compare(car1.Make, car2.Make)
        End If
    End Function)

Another (little less efficient since it needs to recreate the array) approach is LINQ:

Dim orderedCars = from car in arrayOfCars
                  order by car.Make Ascending
arrayOfCars = arrayOfCars.ToArray()

The LINQ approach is more maintainable and easier to read but it needs to create a new array. So if you don't want to modify the original array you should use that.

In general you should not use arrays if you want to add objects since arrays are fixed-sized collections. Use a List(Of Car) instead, it has an Add method.

Another nitpick, follow .NET naming/capitalization conventions, use Car instead of car.




回答2:


Linq is your friend here and the OrderBy method. But in order to use that your array needs to be a List.

You can convert it to a List easily and sort it by the make like this (Not that this does not sort the original list, it creates a new list sorted by the criteria you specify):

Dim sortedListOfCars = arrayOfCars.ToList.OrderBy(Function(x) x.Make)

But it would be easier to declare it as a list to start with:

Dim listOfCars As New List(Of Car)

Then add your cars like this

listOfCars.Add(New Car With {.Make = "Ford", .Year = 1992})
listOfCars.Add(New Car With {.Make = "Fiat", .Year = 1988})
'etc.

Then you just OrderBy directly:

Dim sortedListOfCars = arrayOfCars.OrderBy(Function(x) x.Make)



回答3:


You could implement an IComparer for the Array.Sort() function.

Public Class CarComparer : Implements IComparer
   Function Compare(x As car, y As car) As Integer _
            Implements IComparer.Compare
      Return New CaseInsensitiveComparer().Compare(x.Make, y.Make)
   End Function 
End Class

Use it like this:

Array.Sort(arrayOfCars, new CarComparer())



回答4:


If you're going to have this requirement frequently, you should implement a KeyComparer class. This would allow you to come up with concise syntax, such as:

Array.Sort(arrayOfCars, New KeyComparer(Function(c As car) c.Make))

The Array.Sort(..., Comparison) approach suffers from the disadvantage that it doesn't handle nulls, and would throw NullReferenceException if any of your list elements happen to be null. This may or may not be relevant to your case.

There are plenty of KeyComparer implementations online. I've discussed this specific issue at length – and presented a sample C# implementation – in my KeyComparer article. The VB.NET conversion is below:

Public Class KeyComparer(Of TSource, TKey)
    Inherits Comparer(Of TSource)

    Private ReadOnly _keySelector As Func(Of TSource, TKey)
    Private ReadOnly _innerComparer As IComparer(Of TKey)

    Public Sub New(keySelector As Func(Of TSource, TKey), Optional innerComparer As IComparer(Of TKey) = Nothing)
        _keySelector = keySelector
        _innerComparer = If(innerComparer, Comparer(Of TKey).[Default])
    End Sub

    Public Overrides Function Compare(x As TSource, y As TSource) As Integer
        If Object.ReferenceEquals(x, y) Then
            Return 0
        End If
        If x Is Nothing Then
            Return -1
        End If
        If y Is Nothing Then
            Return 1
        End If

        Dim xKey As TKey = _keySelector(x)
        Dim yKey As TKey = _keySelector(y)
        Return _innerComparer.Compare(xKey, yKey)
    End Function
End Class


来源:https://stackoverflow.com/questions/36470183/to-sort-a-class-array-in-vb-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!