locked
Collections Design Strategy RRS feed

  • Question

  • I would like to sort some information chronologically. I know I could use a Sortedlist if I had one value. Example, if my collection of a year and a person's weight, I could use the year as the index, and the weight as the value.

    What if, instead, I wanted to include a person's height?  I would have year, weight and height. I would have two values.  I still would like to sort the information chronologically, but I don't think this would work with a SortedList.

    Any suggestions would be appreciated.

    Thanks.

    Dave


    Dave Kaufmann

    Monday, August 27, 2012 6:01 PM

Answers

  • You can use a Class and implement the IComparable interface. See the below link for an example:

    http://www.vb-helper.com/howto_net_sort_comparable.html


    Paul ~~~~ Microsoft MVP (Visual Basic)

    • Proposed as answer by Frank L. Smith Monday, August 27, 2012 8:35 PM
    • Marked as answer by Youen Zen Thursday, September 6, 2012 7:26 AM
    Monday, August 27, 2012 7:58 PM
  • You can also add the Person objects to a List(Of Person) and then call the Sort method, passing a Lambda expression which specifies the sort:

    Public Class Form1
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Dim random As New Random
            Dim personList As New List(Of Person)
            For count As Integer = 1 To 10
                Dim p As New Person
                p.BirthYear = random.Next(1940, 2013)
                p.Height = random.Next(54, 78)
                p.Height += random.NextDouble
                p.Weight = random.Next(120, 280)
                p.Weight += random.NextDouble
                personList.Add(p)
            Next
    
            personList.Sort(Function(source As Person, target As Person) source.BirthYear.CompareTo(target.BirthYear))
    
            For Each p As Person In personList
                Debug.Print(p.BirthYear & ", " & p.Height & ", " & p.Weight)
            Next
        End Sub
    End Class
    
    Public Class Person
        Public Property BirthYear As Integer
        Public Property Weight As Double
        Public Property Height As Double
    End Class
    
     

    If the sort is always the same then implementing IComparable on Person may be a better choice.  If you will perform different sorts at different times then you might prefer to provide a comparer to the Sort method.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Proposed as answer by Frank L. Smith Monday, August 27, 2012 8:35 PM
    • Marked as answer by Youen Zen Thursday, September 6, 2012 7:26 AM
    Monday, August 27, 2012 8:27 PM
  • I agree with both Paul and Reed and will add this:

    THINK LINQ!

    Have you considered a database? If you're not comfortable with that, what about an in-memory DataTable?

    Lastly but certainly not least - and if I weren't going to use a database this would be how I'd do it - is this: Use a class (or structure) and a List(of Class) (or structure), then let LINQ do the heavy lifting. It's actually easier than what it might at first seem.

    There are many ways to do this, obviously! :-)


    Please call me Frank :)

    • Marked as answer by Youen Zen Thursday, September 6, 2012 7:26 AM
    Monday, August 27, 2012 8:34 PM

All replies

  • You can use a Class and implement the IComparable interface. See the below link for an example:

    http://www.vb-helper.com/howto_net_sort_comparable.html


    Paul ~~~~ Microsoft MVP (Visual Basic)

    • Proposed as answer by Frank L. Smith Monday, August 27, 2012 8:35 PM
    • Marked as answer by Youen Zen Thursday, September 6, 2012 7:26 AM
    Monday, August 27, 2012 7:58 PM
  • You can also add the Person objects to a List(Of Person) and then call the Sort method, passing a Lambda expression which specifies the sort:

    Public Class Form1
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Dim random As New Random
            Dim personList As New List(Of Person)
            For count As Integer = 1 To 10
                Dim p As New Person
                p.BirthYear = random.Next(1940, 2013)
                p.Height = random.Next(54, 78)
                p.Height += random.NextDouble
                p.Weight = random.Next(120, 280)
                p.Weight += random.NextDouble
                personList.Add(p)
            Next
    
            personList.Sort(Function(source As Person, target As Person) source.BirthYear.CompareTo(target.BirthYear))
    
            For Each p As Person In personList
                Debug.Print(p.BirthYear & ", " & p.Height & ", " & p.Weight)
            Next
        End Sub
    End Class
    
    Public Class Person
        Public Property BirthYear As Integer
        Public Property Weight As Double
        Public Property Height As Double
    End Class
    
     

    If the sort is always the same then implementing IComparable on Person may be a better choice.  If you will perform different sorts at different times then you might prefer to provide a comparer to the Sort method.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Proposed as answer by Frank L. Smith Monday, August 27, 2012 8:35 PM
    • Marked as answer by Youen Zen Thursday, September 6, 2012 7:26 AM
    Monday, August 27, 2012 8:27 PM
  • I agree with both Paul and Reed and will add this:

    THINK LINQ!

    Have you considered a database? If you're not comfortable with that, what about an in-memory DataTable?

    Lastly but certainly not least - and if I weren't going to use a database this would be how I'd do it - is this: Use a class (or structure) and a List(of Class) (or structure), then let LINQ do the heavy lifting. It's actually easier than what it might at first seem.

    There are many ways to do this, obviously! :-)


    Please call me Frank :)

    • Marked as answer by Youen Zen Thursday, September 6, 2012 7:26 AM
    Monday, August 27, 2012 8:34 PM
  • Paul,

    Thanks. I'll give it a try.

    Dave


    Dave Kaufmann

    Monday, August 27, 2012 9:39 PM
  • Reed,

    Thanks. I will consider this.

    Dave


    Dave Kaufmann

    Monday, August 27, 2012 9:42 PM
  • Frank,

    Thanks. I haven't paid much attention to LINQ up to this point.

    I'll check it out.

    Dave


    Dave Kaufmann

    Monday, August 27, 2012 9:43 PM
  • Frank,

    Thanks. I haven't paid much attention to LINQ up to this point.

    I'll check it out.

    Dave


    Dave Kaufmann

    Dave,

    Where is the data coming from? Is it something you're doing in code inside the program or just where?

    Do you already have a database maybe? If so then you already have the collection; it's now a matter of doing what you need to get the value(s) that you need based on the condition(s) that you give it.

    LINQ is an odd looking animal - you'll look at the syntax cross-eyed and think "huh??", but once you sort of get the idea of what's what, what it's looking for and how to get it to return what you want, you'll wonder how you ever did without it!

    I hope this helps. :)


    Please call me Frank :)

    Monday, August 27, 2012 9:49 PM
  • Frank,

    The data will be from user inputs and computations on those inputs. I do not have a traditional database. For a scenario there probably will not be more than 40 items, but there will be lots of computations.

    Dave


    Dave Kaufmann

    Monday, August 27, 2012 10:32 PM
  • Frank,

    The data will be from user inputs and computations on those inputs. I do not have a traditional database. For a scenario there probably will not be more than 40 items, but there will be lots of computations.

    Dave


    Dave Kaufmann

    I see.

    Well you might consider a class with fields then a list of that class.

    For instance:

    Public Class Person
        Public Age As Integer
        Public Weight_In_Pounds As Integer
        Public Height_In_Inches As Integer
    End Class

    Private people As New List(Of Person)

    Something like that anyway. When you have a new entry, you declare a new instance of "Person" and with that new instance, you fill in the various details. Following that (and validation if there is to be any), it's added to the list "people".

    That creates a strongly-typed dataset. With that - and the help of LINQ - you can do all sorts of things and sorting (ordering) is easy no matter what you want to order it by.

    Let's get LINQ to give us a subset of the list (people) where the person is 35 years old or younger:

    Dim qry = From dr As Person In people Where dr.Age <= 35 OrderBy dr.Age DESC

    It just returned a subset of all people less than or equal to 35 and sorted them by age in descending order.

    Give it some thought. :)


    Please call me Frank :)

    Monday, August 27, 2012 11:43 PM
  • Thanks. - Dave

    Dave Kaufmann

    Tuesday, August 28, 2012 2:27 PM