Results 1 to 24 of 24

Thread: Sorting a list of objects

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Sorting a list of objects

    HI. Suppose I have:

    Code:
    Public Class myClass1
        Dim foo As String
        Dim bar As String
        Dim fum As Integer
        Public Sub New(ByVal foo As String, ByVal bar As String, ByVal fum As Integer)
            Me.foo = foo
            Me.bar = bar
            Me.fum = fum
        End Sub
    
    End Class
    .
    .
    .
        Sub main3()
            Dim myList As List(Of myClass1)
            myList.Add(New myClass1("a0", "b0", 0))
            myList.Add(New myClass1("a2", "b2", 2))
            myList.Add(New myClass1("a1", "b1", 1))
            myList.Add(New myClass1("a3", "b3", 4))
    
            ' Sort the list by the foo property
        End Sub
    How would I go about sorting the list by its first property, foo using library methods?

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: Sorting a list of objects

    Take a look in MSDN on the List.Sort method. You will see that there are a number of overloads for this method. One of them will work....but more on that in a minute.

    If you are only EVER going to sort on that first property, then you should have the class implement the IComparer interface. It's pretty easy to do, but easy to forget, as well. Therefore, whenever I want to do that, I generally just go to MSDN and copy the sample that is found there and change it to suit. Once you have that interface implemented, the standard .Sort() method will sorth them correctly.

    However, where I started out going was for those cases where this time you want to sort on one property, but next time you will want to sort on some other property. In those cases, just implementing IComparer won't suffice. In those cases, you will have to create a custom comparison routine and supply it as an argument to the .Sort method, and that's what all those overloads are all about.
    My usual boring signature: Nothing

  3. #3
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Sorting a list of objects

    Here is an example of an implementation of the IComparable<T> interface used for sorting by generic list objects. It compares by age:-
    vbnet Code:
    1. Private Class Data
    2.         Implements IComparable(Of Data)
    3.  
    4.         Private _name As String
    5.         Private _age As Integer
    6.  
    7.         Sub New(ByVal name As String, ByVal age As Integer)
    8.             _name = name
    9.             _age = age
    10.         End Sub
    11.  
    12.         Public Function CompareTo(ByVal other As Data) As Integer Implements System.IComparable(Of Data).CompareTo
    13.             If Me._age < other._age Then Return -1 'When me is less than other
    14.             If Me._age = other._age Then Return 0 'Equal
    15.             If Me._age > other._age Then Return 1 'When me is greater than other
    16.  
    17.         End Function
    18. End Class
    Implement that interface on your class and you can sort like:-
    vbnet Code:
    1. Dim lst As New List(Of Data)
    2.  
    3.         lst.Add(New Data("John", 2))
    4.         lst.Add(New Data("Mary", 12))
    5.         lst.Add(New Data("Mac", 12))
    6.         lst.Add(New Data("Amber", 4))
    7.         lst.Add(New Data("Joe", 77))
    8.  
    9.         lst.Sort()  '<---- Will sort according to Age because thats how IComparable<T> was implemented
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  4. #4
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Sorting a list of objects

    Since your class doesn't have any public properties the only way to go is to implement an IComparable interface.
    Code:
    Public Class myClass1
      Implements IComparable(Of myClass1)
    
      Private foo As String
      Private bar As String
      Private fum As Integer
      Public Sub New(ByVal foo As String, ByVal bar As String, ByVal fum As Integer)
        Me.foo = foo
        Me.bar = bar
        Me.fum = fum
      End Sub
    
      Public Function CompareTo(other As myClass1) As Integer Implements System.IComparable(Of myClass1).CompareTo
        Return String.Compare(Me.foo, other.foo)
      End Function
    End Class
    In this case I implemented the IComparable(Of T) interface and used your class as the type for T. The interface states that you must implement the CompareTo() method. Since you're only comparing strings I simply used the String.Compare() method and returned the value of that.

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Re: Sorting a list of objects

    Quote Originally Posted by Shaggy Hiker View Post
    Take a look in MSDN on the List.Sort method. You will see that there are a number of overloads for this method. One of them will work....but more on that in a minute.

    If you are only EVER going to sort on that first property, then you should have the class implement the IComparer interface. It's pretty easy to do, but easy to forget, as well. Therefore, whenever I want to do that, I generally just go to MSDN and copy the sample that is found there and change it to suit. Once you have that interface implemented, the standard .Sort() method will sorth them correctly. .
    OK -- Working on that. However my test program is failing on the first:

    Code:
    myList.Add(New myClass1("a0", "b0", 0))
    It tells me "Object reference not set to an instance of an object."

    Am I doing something wrong in my "New" method?

  6. #6
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Sorting a list of objects

    Try initializing foo to zero length in myClass1

    EDIT:

    Nvm, there is no default constructor so you have to pass it a value.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  7. #7
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Sorting a list of objects

    Quote Originally Posted by b5177241 View Post
    Code:
    myList.Add(New myClass1("a0", "b0", 0))
    It tells me "Object reference not set to an instance of an object."

    Am I doing something wrong in my "New" method?
    No, it's not in your constructor. The problem is that you never create the object.
    Code:
    Dim myList As New List(Of myClass1)

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: Sorting a list of objects

    Whenever you see that error message, look at the objects on the line that is giving you the error. One of them is Nothing, and that is where the problem lies. It's one of the simplest errors to diagnose, though the solution is not always obvious.

    There is also an exception to that rule: If the error is showing you <some form>.Show or <some form>.ShowDialog, then the error actually didn't happen on that line (unless the form is Nothing), in which case you would need further work to figure out where the error actually occurred.
    My usual boring signature: Nothing

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Re: Sorting a list of objects

    Thanks! FYI, I am not writing forms apps. just CLI apps. I haven't delved into any forms stuff.

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Re: Sorting a list of objects

    This is great! I can use this immediately.

    Today a related question cropped up.

    Say I have an 100 x 2 array. Each of the 100 entries in the first dimension consists of a string and an integer. How would I sort the array by the integer values?

  11. #11
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Sorting a list of objects

    Does it have to be a two dimensional array ? Id prefer to use a List<T> or Collection<T> of a class that can hold my Integer and my String values and apply the methods recommended in this thread. The Array.Sort overloads that take an IComparer based object may be able to sort your two dimensional array, I'm not certain though. Jmc or paul may be able to help with that one.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  12. #12

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Re: Sorting a list of objects

    In this case I'm stuck with the array, since it is a part of a larger project, of which the sorting is just a little bit.

  13. #13
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Sorting a list of objects

    Quote Originally Posted by b5177241 View Post
    This is great! I can use this immediately.

    Today a related question cropped up.

    Say I have an 100 x 2 array. Each of the 100 entries in the first dimension consists of a string and an integer. How would I sort the array by the integer values?
    I don't get it. Is it an array of strings or of integers? Can you give an example of the values?

  14. #14

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Re: Sorting a list of objects

    eg.

    dim a(99,1) as object
    a(0,0) = "foo"
    a(0,1) = 1
    a(1,0) = "bar"
    a(1,1) = 2

  15. #15
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Sorting a list of objects

    Something about that doesn't make any sense. Does that array represent rows ? Because if so then its kind of a bad design as you can access every element independently.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  16. #16
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Sorting a list of objects

    Array.Sort() can only sort a 1-dimensional arrays so you have to write the logic for this yourself.
    Here's a quick example
    Code:
      Public Sub SortArray(ByRef array(,) As Object)
        Dim list As New List(Of KeyValuePair(Of String, Integer))
        Dim count = array.GetUpperBound(0)
        For i = 0 To count
          list.Add(New KeyValuePair(Of String, Integer)(CStr(array(i, 0)), CInt(array(i, 1))))
        Next
        list.Sort(Function(firstPair, secondPair) firstPair.Value.CompareTo(secondPair.Value))
        For i = 0 To count
          array(i, 0) = list(i).Key
          array(i, 1) = list(i).Value
        Next
      End Sub

  17. #17
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Sorting a list of objects

    Quote Originally Posted by b5177241 View Post
    eg.

    dim a(99,1) as object
    a(0,0) = "foo"
    a(0,1) = 1
    a(1,0) = "bar"
    a(1,1) = 2
    you could use a bubble sort:

    vb Code:
    1. Dim a(9, 1) As Object
    2. a(0, 0) = "c"
    3. a(0, 1) = 3
    4. a(1, 0) = "i"
    5. a(1, 1) = 9
    6. a(2, 0) = "f"
    7. a(2, 1) = 6
    8. a(3, 0) = "a"
    9. a(3, 1) = 1
    10. a(4, 0) = "d"
    11. a(4, 1) = 4
    12. a(5, 0) = "j"
    13. a(5, 1) = 10
    14. a(6, 0) = "g"
    15. a(6, 1) = 7
    16. a(7, 0) = "b"
    17. a(7, 1) = 2
    18. a(8, 0) = "e"
    19. a(8, 1) = 5
    20. a(9, 0) = "h"
    21. a(9, 1) = 8
    22.  
    23. 'bubble sort
    24. For outer As Integer = a.GetUpperBound(0) To 0 Step -1
    25.     For inner As Integer = 0 To outer - 1
    26.         If CInt(a(inner, 1)) > CInt(a(inner + 1, 1)) Then
    27.             Dim temp() As Object = {a(inner, 0), a(inner, 1)}
    28.             a(inner, 0) = a(inner + 1, 0)
    29.             a(inner, 1) = a(inner + 1, 1)
    30.             a(inner + 1, 0) = temp(0)
    31.             a(inner + 1, 1) = temp(1)
    32.         End If
    33.     Next
    34. Next

  18. #18
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: Sorting a list of objects

    I would suggest that there is never a justification to have an array of that nature. Creating an array of object just so that you can use strings and integers means that you have to cast everything to use it, and there should be plenty of other costly boxing and unboxing along the way. In most cases, a 2D array can be replaced by a 1D array of some class, and this is certainly such a case. Doing that would remove the problems with sorting, as well as making for a more efficient routine. Considering that the class would only have an integer and a string, a structure might also make sense.
    My usual boring signature: Nothing

  19. #19

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Re: Sorting a list of objects

    Quote Originally Posted by .paul. View Post
    you could use a bubble sort:

    I hope your kidding. Bubble sort is one of the worst sort methods and is O(n^2). A randomized quicksort would be much better and not much more work (O(n log n).

    OTOH for 100 rows it wouldn't make much difference in practice.

    What I am looking for is a way to use library functions. I think I have enough to go on for that.

  20. #20

    Thread Starter
    Lively Member
    Join Date
    Jan 2012
    Posts
    122

    Re: Sorting a list of objects

    Quote Originally Posted by Shaggy Hiker View Post
    I would suggest that there is never a justification to have an array of that nature.
    I agree. In my case I "inherited" the array from others in the project. I can try to persuade the team to alter the approach. In the meantime, I just need to find the best way to work with what I'm given.

  21. #21
    Frenzied Member MattP's Avatar
    Join Date
    Dec 2008
    Location
    WY
    Posts
    1,227

    Re: Sorting a list of objects

    I concur with Shaggy Hiker on this. A 1D array (or even better collection) of a class/structure makes much more sense.

    To facilitate sorting a rectangular array on a specific column I created a couple of extension methods for converting the array from rectangular to jagged and back.

    Code:
    Imports System.Runtime.CompilerServices
    
    Public Module SortHelper
    
        <System.Runtime.CompilerServices.Extension()> _
        Public Function ToJagged(Of T)(array As T(,)) As T()()
            Dim height As Integer = array.GetLength(0), width As Integer = array.GetLength(1)
            Dim jagged As T()() = New T(height - 1)() {}
    
            For i As Integer = 0 To height - 1
                Dim row As T() = New T(width - 1) {}
                For j As Integer = 0 To width - 1
                    row(j) = array(i, j)
                Next
                jagged(i) = row
            Next
            Return jagged
        End Function
    
        <System.Runtime.CompilerServices.Extension()> _
        Public Function ToRectangular(Of T)(array As T()()) As T(,)
            Dim height As Integer = array.Length, width As Integer = array(0).Length
            Dim rect As T(,) = New T(height - 1, width - 1) {}
            For i As Integer = 0 To height - 1
                Dim row As T() = array(i)
                For j As Integer = 0 To width - 1
                    rect(i, j) = row(j)
                Next
            Next
            Return rect
        End Function
    
    End Module
    Here's a small example array and a generic Sort method.

    Code:
    Public Class Form1
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Dim a(9, 1) As Object
            a(0, 0) = "c"
            a(0, 1) = 3
            a(1, 0) = "i"
            a(1, 1) = 9
            a(2, 0) = "f"
            a(2, 1) = 6
            a(3, 0) = "a"
            a(3, 1) = 1
            a(4, 0) = "d"
            a(4, 1) = 4
            a(5, 0) = "j"
            a(5, 1) = 10
            a(6, 0) = "g"
            a(6, 1) = 7
            a(7, 0) = "b"
            a(7, 1) = 2
            a(8, 0) = "e"
            a(8, 1) = 5
            a(9, 0) = "h"
            a(9, 1) = 8
    
            Dim jagged = a.ToJagged()
            Sort(jagged, 1)
            a = jagged.ToRectangular()
        End Sub
    
        Private Shared Sub Sort(Of T)(jaggedArray As T()(), col As Integer)
            Dim comp = Comparer(Of T).Default
            Array.Sort(Of T())(jaggedArray, Function(x, y) comp.Compare(x(col), y(col)))
        End Sub
    
    End Class
    Last edited by MattP; Mar 19th, 2012 at 02:14 PM.

  22. #22
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: Sorting a list of objects

    Such is life, at times.
    My usual boring signature: Nothing

  23. #23
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Sorting a list of objects

    Quote Originally Posted by b5177241 View Post
    OTOH for 100 rows it wouldn't make much difference in practice.
    as you said for a small array it would work ok...

  24. #24
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Sorting a list of objects

    Quote Originally Posted by b5177241 View Post
    What I am looking for is a way to use library functions. I think I have enough to go on for that.
    As I mentioned in my previous reply there is no library functions to sort a multiple dimensional array. The closest you can come is to use code similar to what I showed or just use a regular bubble- or quick sort routine (bubble sort will most likely be quicker when you only have 100 items).

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width