2016-04-07 4 views
3

Я потратил 2 дня на поиск Интернета, пытаясь найти решение, просто отсортировав массив, состоящий из класса строк и целых чисел (всего одним из элементов строки, который может содержать нерегулярные символы). Пожалуйста помоги! Я создал упрощенный код, что я пытаюсь сделать на основе майкрософт например:Чтобы отсортировать массив классов в vb.net

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 
+0

Как вы хотели бы заниматься поиском, только по собственному усмотрению 'Make'? –

ответ

2

Если вы хотите отсортировать по Make собственности одного вне коробки подход использует Array.Sort с Comparison(Of T) перегрузки:

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

Заметим, что вы должны позаботиться о машинах, которые являются Nothing или (скорее) Make -значения, которые являются Nothing. Оба могут вызвать NullReferenceException. Таким образом, вы можете использовать:

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) 

Другой (чуть менее эффективно, так как для этого нужно воссоздать массив) подход LINQ:

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

подход LINQ становится более сопровождаемым, и легче читать, но она должна создайте новый массив. Поэтому, если вы не хотите изменять исходный массив, вы должны использовать его.

В общем случае вы не должны использовать массивы, если хотите добавить объекты, поскольку массивы представляют собой коллекции фиксированного размера. Используйте вместо этого List(Of Car), он имеет Add method.

Другой nitpick, следуйте за .NET naming/capitalization conventions, используйте Car вместо car.

+0

Ничего себе, спасибо Тим. Два решения, с которыми я могу работать! Я рассмотрю инструмент списка. – James

+1

@james: добро пожаловать. Обратите внимание, что 'List (Of T)' является классом (а не инструментом), который содержит массив для элементов, но автоматически увеличивает его размер, если вы добавляете элементы. Не забудьте принять ответ. –

1

Linq является вашим другом здесь и метод OrderBy. Но для того, чтобы использовать это, ваш массив должен быть List.

Вы можете преобразовать его в список легко и сортировать его по маркам, как это (Не то, чтобы это не сортирует первоначальный список, он создает новый список, отсортированный по заданному критерию):

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

Но было бы проще объявить его в виде списка, чтобы начать с:

Dim listOfCars As New List(Of Car) 

Затем добавить свои автомобили, как это

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

Тогда вы просто OrderBy непосредственно:

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

Спасибо за вашу помощь Мэтт, я рассмотрю использование функции «Список» для будущих проектов. – James

0

Вы можете реализовать IComparer для функции Array.Sort().

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 

Используйте это так:

Array.Sort(arrayOfCars, new CarComparer()) 
0

Если вы собираетесь это требование часто, вы должны реализовать KeyComparer класс.Это позволит вам придумать краткий синтаксис, например:

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

Array.Sort(..., Comparison) подход страдает тем недостатком, что она не обрабатывает аннулирует, и будет бросать NullReferenceException, если какой-либо из списка ваших элементов случается быть пустым , Это может быть или не иметь отношения к вашему делу.

Существует множество вариантов использования KeyComparer. Я подробно обсудил эту конкретную проблему и представил пример реализации C# - в моем KeyComparer article. Преобразование VB.NET приведено ниже:

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