Results 1 to 9 of 9

Thread: **SORTED :) tx rj** Sorting 2D arrays on any column

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    350

    Question **SORTED :) tx rj** Sorting 2D arrays on any column

    Gang,

    I've just spent ages searching the site. There's a huge amount of stuff on sorting arrays, with attendant debate about which algo is best.

    But as far as I can see, there's none that do a sort of a 2d array on any column. I'd like to see the user quizzed for "What field (=column) do you want to sort the records (=rows) on?" and Robert's your Dad's* brother.

    Anyone?



    * or Mum's
    Last edited by Jim Brown; Aug 8th, 2002 at 05:22 AM.
    .

  2. #2
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    The code for the sorting is the hard part...

    the easy part is adapting it to your needs...

    I think it would be in your best interest to help everyone along ...
    with information such as:

    how is the array dimensioned? (I realize its a 2-d array, but what sizes)

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    350
    Not huge arrays. Probably about a couple of hundred records (maybe 1000 absolute max) of about 40 fields.

    And while I think about it, it would be nice to do a sort on more than one column, eg perhaps first on UserName then on Date within.

    BTW I'm not expecting anyone to sit and write this for me because I'll be very surprised if it doesn't exist somewhere already!
    .

  4. #4
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Basically it comes down to how you feed the sort algorithm...

    so if you had

    rec1: LastName FirstName MiddleName

    you feed the LastName field into the Sort algorithm, and modifiy the algorithm to compare FirstName's only if the LastName comparison is indetermine (the names are equal). As you see below, if the first bolded line comparison cases to 0 (equal), the algorithm then checks the FirstNames (2nd bolded line), if those are equal, check the middlenames...

    VB Code:
    1. Do While incr > 0
    2.         For i = incr To UBound(patientarray) Step 1
    3.             j = i - incr
    4.             Do While j >= 0
    5.                 [b]Select Case StrComp(patientarray(j).LName, patientarray(j + incr).LName, 1)[/b]
    6.                
    7.                 Case 1:
    8.                    
    9.                     temp = patientarray(j)
    10.                     patientarray(j) = patientarray(j + incr)
    11.                     patientarray(j + incr) = temp
    12.                     j = j - incr
    13.                 Case 0:
    14.                     [b]Select Case StrComp(patientarray(j).FName, patientarray(j + incr).FName, 1)[/b]
    15.                         Case 1:
    16.                        
    17.                         temp = patientarray(j)
    18.                         patientarray(j) = patientarray(j + incr)
    19.                         patientarray(j + incr) = temp
    20.                         j = j - incr
    21.                        
    22.                         Case 0:[b]
    23.                         Select Case StrComp(patientarray(j).MName, patientarray(j + incr).MName, 1)[/b]
    24.                             Case 1:
    25.                                 temp = patientarray(j)
    26.                                 patientarray(j) = patientarray(j + incr)
    27.                                 patientarray(j + incr) = temp
    28.                                 j = j - incr
    29.                             Case 0:
    30.                                 Select Case StrComp(patientarray(j).BDate, patientarray(j + incr).BDate, 0)
    31.                                     Case 1:
    32.                                           temp = patientarray(j)
    33.                                           patientarray(j) = patientarray(j + incr)
    34.                                           patientarray(j + incr) = temp
    35.                                           j = j - incr
    36.                                     Case 0:

    Or, to sort on just any ONE field (meaning not considering the order of other fields), you simply feed that field to the algorithm...

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    350
    Thanks, I'll give that a try later today- I'm on my way out soon.

    In the meantime, if anyone else has any suggestions, I'm keen to hear them!

    Ciao.
    .

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    350
    Nemaroller- you seem to have chopped off the bottom of your code. If you have a chance can you pop the rest of it in please...
    .

  7. #7
    PowerPoster rjlohan's Avatar
    Join Date
    Sep 2001
    Location
    Sydney, Australia
    Posts
    3,205
    For this code, add two textboxes (txtArrayOutput) (Index 0 for original array, index 1 for sorted array), you need 2 buttons, and a text box, labelled as the code suggests:

    (I've also attached it as a .zip)

    VB Code:
    1. Option Explicit
    2.  
    3. 'Data array
    4. Private MyArray() As Variant
    5.  
    6. 'Column identifiers
    7. Private Const NUMBER = 0
    8. Private Const X3_CHAR_CODE = 1
    9. Private Const X10_CHAR_STRING = 2
    10.  
    11. 'Enum for output textbox
    12. Private Enum TextType
    13.     TXT_ORIGINAL_ARRAY = 0
    14.     TXT_SORTED_ARRAY = 1
    15. End Enum
    16.  
    17.  
    18. Private Sub btnCreateArray_Click()
    19.     'Counter
    20.     Dim i As Integer
    21.    
    22.     'Dim array
    23.     ReDim MyArray(2, 5)
    24.    
    25.     'Fill array
    26.     For i = 0 To (UBound(MyArray, 2) - 1)
    27.         MyArray(NUMBER, i) = CInt(rnd * 100)
    28.         MyArray(X3_CHAR_CODE, i) = Chr((rnd * 25) + 65) & Chr((rnd * 25) + 65) & Chr((rnd * 25) + 65)
    29.         MyArray(X10_CHAR_STRING, i) = Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31) & Chr((rnd * 94) + 31)
    30.     Next
    31.    
    32.     'Display original array
    33.     Call DisplayArray(TXT_ORIGINAL_ARRAY)
    34.    
    35.     'Enable sort buttons
    36.     btnSortArray.Enabled = True
    37. End Sub
    38.  
    39.  
    40. 'Uses bubble sort method
    41. Private Sub btnSortArray_Click()
    42.     'Counters
    43.     Dim i As Long
    44.     Dim j As Long
    45.     Dim n As Long
    46.     Dim allOk As Boolean
    47.    
    48.     'Temp array - should be same size as 1 record of MyArray
    49.     ReDim tempN(UBound(MyArray, 1)) As Variant
    50.    
    51.     'Set sort column value
    52.     Dim SC As Integer
    53.     SC = CInt(txtColumn.Text)
    54.    
    55.     'Check sort column boundary
    56.     If ((SC < 0) Or (SC > UBound(MyArray, 1))) Then
    57.         MsgBox ("Invalid sort column entered.")
    58.         Exit Sub
    59.     End If
    60.    
    61.     'Sort array by first column
    62.     For n = 0 To UBound(MyArray, 2)
    63.         allOk = True
    64.         For i = 0 To UBound(MyArray, 2) - 1
    65.             If MyArray(SC, i) > MyArray(SC, i + 1) Then
    66.                 allOk = False
    67.                 'Get temp element
    68.                 For j = 0 To UBound(tempN)
    69.                     tempN(j) = MyArray(j, i)
    70.                     MyArray(j, i) = MyArray(j, i + 1)
    71.                     MyArray(j, i + 1) = tempN(j)
    72.                 Next
    73.             End If
    74.         Next
    75.         If allOk Then Exit For
    76.     Next
    77.    
    78.     'Display sorted array
    79.     Call DisplayArray(TXT_SORTED_ARRAY)
    80. End Sub
    81.  
    82.  
    83. Private Sub DisplayArray(TT As TextType)
    84.     'Clear chosen textbox
    85.     txtArrayOutput(TT).Text = ""
    86.    
    87.     'Display array on chosen textbox
    88.     Dim i As Integer
    89.     For i = TT To (UBound(MyArray, 2) - (1 - TT))
    90.         txtArrayOutput(TT).Text = txtArrayOutput(TT).Text & _
    91.             CStr(MyArray(NUMBER, i)) & " : " & _
    92.             CStr(MyArray(X3_CHAR_CODE, i)) & " : " & _
    93.             CStr(MyArray(X10_CHAR_STRING, i)) & vbNewLine
    94.     Next
    95. End Sub
    96.  
    97.  
    98. Private Sub txtColumn_KeyPress(KeyAscii As Integer)
    99.     'Disallow non-numeric entries
    100.     If ((KeyAscii < vbKey0) Or (KeyAscii > vbKey9)) Then
    101.         If (KeyAscii <> vbKeyBack) Then KeyAscii = 0
    102.     End If
    103. End Sub


    I know it looks long, but there's auxilliary crap in there (creating an array, displaying the results, etc). Also, I've implemented this on a variant array, using a bubble sort method I pinched from Jamie. The sort method is arbitrary really, this one just didn't involve much code.

    I'd have gone further and sorted on multiple columns, but the logic behind that escapes me at the moment. Anyway, the architecture is there, you're a smart boy, you can work it out.

    To implement this fully in your solution, I suggest creating a 2nd 2D array to store a pair of COLUMN_NAME, COLUMN_INDEX for a better UI. Hopefully you can slip all that in there.

    Attached Files Attached Files
    -----------------------------------------
    -RJ
    [email protected]
    -----------------------------------------

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2000
    Posts
    350
    Thanks RJ, I'll give that a bash.
    .

  9. #9
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555
    If you use this function to compare the rows, then you should be able to sort on an arbitrary number/order of columns. I haven't tested it however.
    VB Code:
    1. Private Function CompareElements(Element1() As Variant, Element2() As Variant, SortColumns() As Integer) As Integer
    2.   ' Compares the two arrays Element1 and Element2 on their elements in the order defined by SortColumns
    3.   ' Returns 0 if they are equivalent
    4.   ' Returns 1 if Element1 occurs *before* Element2
    5.   ' Returns 2 if Element1 occurs *after* Element2
    6.   ' If the column index given in SortColumns is out of bounds for Element1 or Element2, act as follows:
    7.   '   If it is out of bounds for both, return 0 (both equivalent)
    8.   '   If it is out of boubds for just one, return as though the one that is in bounds occurs *after* the other
    9.   ' A 'Null' entry counts as *before* anything else
    10.  
    11.   Dim Compared As Boolean
    12.   Dim i As Integer
    13.   Dim LowEl1 As Integer, UpEl1 As Integer, LowEl2 As Integer, UpEl2 As Integer
    14.   Dim CurrSortIndex As Integer
    15.  
    16.   CompareElements = 0
    17.   Compared = False
    18.   i = LBound(SortColumns)
    19.   LowEl1 = LBound(Element1)
    20.   UpEl1 = UBound(Element1)
    21.   LowEl2 = LBound(Element2)
    22.   UpEl2 = UBound(Element2)
    23.  
    24.   Do While Not Compared And i <= UBound(SortColumns)
    25.     CurrSortIndex = SortColumns(i)
    26.     If CurrSortIndex < LowEl1 Or CurrSortIndex > UpEl1 Then
    27.       ' Element1 out of bounds, check Element2
    28.       If CurrSortIndex < LowEl2 Or CurrSortIndex > UpEl2 Then
    29.         ' Element2 out of bounds as well, return 0
    30.         CompareElements = 0
    31.         Compared = True
    32.        
    33.       Else
    34.         ' Only Element1 out of bounds, return 1
    35.         CompareElements = 1
    36.         Compared = True
    37.        
    38.       End If
    39.     ElseIf CurrSortIndex < LowEl2 Or CurrSortIndex > UpEl2 Then
    40.       ' Element2 out of bounds but Element1 isn't, return 2
    41.       CompareElements = 2
    42.       Compared = True
    43.      
    44.     Else
    45.       ' Just compare them
    46.       If Element1 < Element2 Then
    47.         CompareElements = 1
    48.         Compared = True
    49.       ElseIf Element1 > Element2 Then
    50.         CompareElements = 2
    51.         Compared = True
    52.       ElseIf Element1 = Element2 Then
    53.         ' Skip to the next column
    54.       Else
    55.         ' One or other is null.
    56.         If Element1 Is Null Then
    57.           If Element2 Is Null Then
    58.             ' Both null, continue checking with next column
    59.           Else
    60.             ' Element1 Null, Element2 not Null
    61.             CompareElements = 1
    62.             Compared = True
    63.           End If
    64.         ElseIf Element2 Is Null Then
    65.           ' Element1 not Null, Element2 Null
    66.           CompareElements = 2
    67.           Compared = True
    68.         Else
    69.          ' Any cases I haven't considered should be equal
    70.         End If
    71.       End If
    72.     End If
    73.   Loop
    74.  
    75. End Function

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