Results 1 to 14 of 14

Thread: Sorting 2 Array but keeping them indexed.

  1. #1

    Thread Starter
    Member
    Join Date
    Dec 2014
    Posts
    57

    Question Sorting 2 Array but keeping them indexed.

    What I have is two fields within a single array that I want to sort based off of the 2nd element first, then sort the first element without mixing the array back up. I know there is something here that I don't know. Please Teach me this.

    If I have a list that looks like this...

    2000 Ford Fiesta
    2000 Ford Escort
    2001 Ford Fiesta
    1999 Ford Escort

    I want to first sort the Make, then sort by Year. I have gone as far as to create an ID tag to place on two arrays separating the Year from the Make, that allows for the first sort to work, but when it comes to making the second sort, I am lost. Any help will do, but I prefer the right help over the wrong.

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

    Re: Sorting 2 Array but keeping them indexed.

    There are overloads for Sort that take an argument. Take a look at this link:

    http://msdn.microsoft.com/en-us/libr...v=vs.110).aspx

    The example at the bottom shows an example. What you need to do is take that example and change the ReverseComparer class (which is really just there to provide a place to host the Compare method).

    An alternative which may be somewhat easier is to convert the array to a List using .ToList, then use a variation of the List.Sort that takes a Comparison of (T) as seen in this link:

    http://msdn.microsoft.com/en-us/libr...v=vs.110).aspx

    Particularly, note this code from the example:

    Code:
            ' This shows calling the Sort(Comparison(T) overload using  
            ' an anonymous delegate method.  
            ' This method treats null as the lesser of two values.
            parts.Sort(Function(x As Part, y As Part)
                                 If x.PartName Is Nothing AndAlso y.PartName Is Nothing Then 
                                     Return 0
                                 ElseIf x.PartName Is Nothing Then 
                                     Return -1
                                 ElseIf y.PartName Is Nothing Then 
                                     Return 1
                                 Else 
                                     Return x.PartName.CompareTo(y.PartName)
                                 End If 
                             End Function)
    Either way, the key to the problem is providing a custom comparison method, whether as a class member as seen in the first example, or as a Comparison (of T) as seen in the second example. The goal of that method is that, given two items A and B, return 1 if A should sort above B, -1 if A should sort below B, or 0 if the two should remain the same.

    In your case, the method would split A and B on space, such that year, make, and model were all separated out for both A and B. This would look something like this:

    Code:
    Public Function CompareTo(A as String, B As String) As Integer
     Dim aArray as String() = A.Split(" ")
     Dim bArray as String() = B.Split(" ")
     
     'You really should check that both arrays have three elements:
     If aArray.Length<>3 OrElse bArray.Length<>3 Then
       Return 0 'One of them doesn't even compare well, so what do you do?
     Else
      'Compare the Make:
      Dim ret As Integer = aArray(1).CompareTo(bArray(1))
      If ret = 0 Then
       'Thus far they are equal, so compare year.
       Return aArray(0).CompareTo(bArray(0))
      Else
       Return ret
      End If
     End If
    End Function
    There are some quirks to that. For one thing, I assume that all years will always be the full four digit year. You can also get some odd results if you have odd things in the array. Still, it is roughly what you are looking for.
    My usual boring signature: Nothing

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

    Re: Sorting 2 Array but keeping them indexed.

    try this:

    Code:
    Dim cars As New List(Of String)(New String() {"2000 Ford Fiesta", "2000 Ford Escort", "2001 Ford Fiesta", "1999 Ford Escort"})
    cars = cars.OrderBy(Function(s) Split(s, " ", 2)(1)).ThenBy(Function(s) CInt(Split(s, " ", 2)(0))).ToList

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

    Re: Sorting 2 Array but keeping them indexed.

    Then there's that way. Sure looks more compact.

    I generally am not enamored of that approach, but in this case I think it would perform pretty well. There are some things about it that are not efficient, but it sure is compact. In the end, it just shows that there are many ways to skin this cat....if cat skinning is an interest of yours.
    My usual boring signature: Nothing

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

    Re: Sorting 2 Array but keeping them indexed.

    Quote Originally Posted by Shaggy Hiker View Post
    Then there's that way...
    yep my own favourite flavour of skinned cat

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

    Re: Sorting 2 Array but keeping them indexed.

    If you already have 2 arrays with associated values, there is also an overload of Array.Sort where you can sort 2 arrays simultaneously, based on the values in 1 of the arrays.
    I'm not sure if Shaggy mentioned that, but it wouldn't work well with your list...

  7. #7

    Thread Starter
    Member
    Join Date
    Dec 2014
    Posts
    57

    Re: Sorting 2 Array but keeping them indexed.

    Ok, I did this.

    Code:
            Dim cars As List(Of String) = ar2.ToList
            cars = cars.OrderBy(Function(s) Split(s, " ", 2)(1)).ThenBy(Function(s) CInt(Split(s, " ", 2)(0))).ToList
            ar2 = cars.ToArray
    and got this:
    Index was outside the bounds of the array. What did I do wrong?

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

    Re: Sorting 2 Array but keeping them indexed.

    What exactly does ar2.ToList hold?
    It'll work if you have each element as you suggested in your OP, with no empty elements

  9. #9

    Thread Starter
    Member
    Join Date
    Dec 2014
    Posts
    57

    Re: Sorting 2 Array but keeping them indexed.

    I forgot to mention the highlight was on this: Function(s) Split(s, " ", 2)(1)

    It holds the same type of list. Say I am an owner of a gazillion orchards. I take inventory of each...

    1002 apples
    1001 apples
    1990 grapes
    1200 apples with worms
    1500 apples
    2000 grapes

    The point is to sort two sides of a string separated by the first space. I get that, and I have this whole project licked for a bit, and would owe someone big time.

  10. #10

    Thread Starter
    Member
    Join Date
    Dec 2014
    Posts
    57

    Re: Sorting 2 Array but keeping them indexed.

    ar2 only contains 29 items, but that shouldn't help you. My project is to scrub data, keep relevant, sort by two levels, present it in CSV which has been complete except for the sort which I nearly had before I lost my head in double decker logic. Been working this for two days straight, and am being quite humble now to seek help.

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

    Re: Sorting 2 Array but keeping them indexed.

    Code:
    'if you want to use arrays:
    Dim orchards(5) As String
    orchards(0) = "1002 apples"
    orchards(1) = "1001 apples"
    orchards(2) = "1990 grapes"
    orchards(3) = "1200 apples with worms"
    orchards(4) = "1500 apples"
    orchards(5) = "2000 grapes"
    
    orchards = orchards.OrderBy(Function(s) Split(s, " ", 2)(1)).ThenBy(Function(s) CInt(Split(s, " ", 2)(0))).ToArray
    Stop
    'no problem for me, but if:
    ReDim Preserve orchards(6)
    orchards = orchards.OrderBy(Function(s) Split(s, " ", 2)(1)).ThenBy(Function(s) CInt(Split(s, " ", 2)(0))).ToArray
    'element at index 6 is empty, which causes an error as after splitting nothing you don't have an index at 1, as used in the OrderBy part of the sorting
    Stop

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

    Re: Sorting 2 Array but keeping them indexed.

    to rephrase that into a more easily understood explanation:

    orchard(6) = ""
    Split(orchard(6), " ", 2) returns a 1 dimensional array of string with 1 empty ("") element

    OrderBy(Function(s) Split(s, " ", 2)(1)) attempts to use the element at index 1 from the Split array, which doesn't exist.

    if execution ever got past that error, you'd get another error in the ThenBy part as CInt("") causes an InvalidCastException

  13. #13

    Thread Starter
    Member
    Join Date
    Dec 2014
    Posts
    57

    Re: Sorting 2 Array but keeping them indexed.

    True as I am now figuring out. I see a pest in my data scrubbing. I am ridding that to see if it fixes the issue.

  14. #14

    Thread Starter
    Member
    Join Date
    Dec 2014
    Posts
    57

    Re: Sorting 2 Array but keeping them indexed.

    You da Man! Works like a charm. Thanks a bundle.

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