ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Sorting multiple DS fields

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Sorting multiple DS fields

    I have a DS defined as below -

    D MyDSArr DS qualified dim(999)
    D MyDsKey
    D field1 10A overlay(MyDsKey:*next)
    D field2 10A overlay(MyDsKey:*next)
    D field3 10A overlay(MyDsKey:*next)
    D field4 7S 0
    D date 8A
    D time 6A


    Now, my requirement is to sort the DS first by date in descending order, followed by time in descending order.

    For a single field, I know that i can sort as below -

    SortA(D) %Subarr(MyDsArr(*).date:1:i)

    And this works fine too. But, is there a way to sort 2 fields? I have read about QSORT utility, but is there any other way to do this?

  • #2
    qsort is really your best option in cases like this - easy to use - I've written a number of articles on it but this one serves https://www.itjungle.com/2012/01/25/fhg012512-story02/

    Not sure why you bothered with MyDSkey in this scenario unless you need it for other purposes.

    Depending on the way that the dsate/time is represented (for example is the time 24 hour clock?) you could in this one instance potentially do this:

    Code:
    [B]  date  char(8);
      time  char(6);
    [/B]dateTime char(14)  SamePos(date);
    
    // Now sort on dateTime
    [B][/B]


    Coding this makes me realize why I prefer free-form!


    Comment


    • #3
      Since SORTA is a stable sort, you may be able to get by with sorting it twice, first by time, then by date. But, I think QSORT or a group field would be better choices.

      Comment


      • #4
        Some years ago I have created a RFE for the possibility to specify a compare procedure for SORTA and %LOOKUPxx

        If you haven't voted for it yet, please do it.
        It might promote that they implement it in RPG.

        http://www.ibm.com/developerworks/rfe/execute?use_case=viewRfe&CR_ID=115361

        Comment


        • #5
          Originally posted by JonBoy View Post
          qsort is really your best option in cases like this - easy to use - I've written a number of articles on it but this one serves https://www.itjungle.com/2012/01/25/fhg012512-story02/

          Not sure why you bothered with MyDSkey in this scenario unless you need it for other purposes.

          Depending on the way that the dsate/time is represented (for example is the time 24 hour clock?) you could in this one instance potentially do this:

          Code:
          [B] date char(8);
          time char(6);
          [/B]dateTime char(14) SamePos(date);
          
          // Now sort on dateTime
          [B][/B]


          Coding this makes me realize why I prefer free-form!

          Thanks JonBoy for your reply. I use MyDSKey for other purposes. I actually coded my logic as you mentioned only (datetime - 14 character field). Was trying to see if i could fit in SORTA logic itself. I havent used QSORT utility before, but will have a check on the article you mentioned. Thanks again

          Comment


          • #6
            Originally posted by Scott Klement View Post
            Since SORTA is a stable sort, you may be able to get by with sorting it twice, first by time, then by date. But, I think QSORT or a group field would be better choices.
            Thanks Scott for your reply. If i understand you correctly, I need to store the results of first sort, and then perform second sort? I will have a look at QSORT utility.

            Comment


            • #7
              Actually, the Shell Sort that SORTA uses isn't a stable sort. So if you sort by one key and then by another, the second sort would not necessarily maintain the first ordering.

              For this program, the first sort is according to "key2" and the second is according to "key1". After the second sort, the key2 values for key1=key1b end up as key2b, key2d, key2e, key2c.
              Code:
              dcl-ds ds;                                
                 info dim(10);                          
                    key1 char(10) overlay(info:*next);  
                    key2 char(10) overlay(info:*next);  
                    data char(10) overlay(info:*next);  
              end-ds;                                    
              info(1 ) = 'key1a     key2g     elem 1 ';  
              info(2 ) = 'key1c     key2f     elem 2 ';  
              info(3 ) = 'key1b     key2e     elem 3 ';  
              info(4 ) = 'key1a     key2i     elem 4 ';  
              info(5 ) = 'key1b     key2d     elem 5 ';  
              info(6 ) = 'key1d     key2h     elem 6 ';  
              info(7 ) = 'key1b     key2c     elem 7 ';  
              info(8 ) = 'key1b     key2b     elem 8 ';  
              info(9 ) = 'key1e     key2j     elem 9 ';  
              info(10) = 'key1e     key2a     elem 10';
              
              sorta key2;                                  
              sorta key1;                                  
              *inlr = *on;
              After the first SORTA:
              Code:
              > EVAL info                                        
                INFO OF DS(1) = 'key1e     key2a     elem 10   '  
                INFO OF DS(2) = 'key1b     key2b     elem 8    '  
                INFO OF DS(3) = 'key1b     key2c     elem 7    '  
                INFO OF DS(4) = 'key1b     key2d     elem 5    '  
                INFO OF DS(5) = 'key1b     key2e     elem 3    '  
                INFO OF DS(6) = 'key1c     key2f     elem 2    '  
                INFO OF DS(7) = 'key1a     key2g     elem 1    '  
                INFO OF DS(8) = 'key1d     key2h     elem 6    '  
                INFO OF DS(9) = 'key1a     key2i     elem 4    '  
                INFO OF DS(10)= 'key1e     key2j     elem 9    '
              After the second SORTA:
              Code:
              > EVAL info                                          
                INFO OF DS(1) = 'key1a     key2g     elem 1    '    
                INFO OF DS(2) = 'key1a     key2i     elem 4    '    
                INFO OF DS(3) = 'key1b     key2b     elem 8    '    
                INFO OF DS(4) = 'key1b     key2d     elem 5    '    
                INFO OF DS(5) = 'key1b     key2e     elem 3    '    
                INFO OF DS(6) = 'key1b     key2c     elem 7    '  <--- out of order
                INFO OF DS(7) = 'key1c     key2f     elem 2    '    
                INFO OF DS(8) = 'key1d     key2h     elem 6    '    
                INFO OF DS(9) = 'key1e     key2a     elem 10   '    
                INFO OF DS(10)= 'key1e     key2j     elem 9    '

              Comment


              • #8
                Actually, the Shell Sort that SORTA uses isn't a stable sort. So if you sort by one key and then by another, the second sort would not necessarily maintain the first ordering.

                For this program, the first sort is according to "key2" and the second is according to "key1". After the second sort, the key2 values for key1=key1b end up as key2b, key2d, key2e, key2c.
                Code:
                dcl-ds ds;                                
                   info dim(10);                          
                      key1 char(10) overlay(info:*next);  
                      key2 char(10) overlay(info:*next);  
                      data char(10) overlay(info:*next);  
                end-ds;                                    
                info(1 ) = 'key1a     key2g     elem 1 ';  
                info(2 ) = 'key1c     key2f     elem 2 ';  
                info(3 ) = 'key1b     key2e     elem 3 ';  
                info(4 ) = 'key1a     key2i     elem 4 ';  
                info(5 ) = 'key1b     key2d     elem 5 ';  
                info(6 ) = 'key1d     key2h     elem 6 ';  
                info(7 ) = 'key1b     key2c     elem 7 ';  
                info(8 ) = 'key1b     key2b     elem 8 ';  
                info(9 ) = 'key1e     key2j     elem 9 ';  
                info(10) = 'key1e     key2a     elem 10';
                
                sorta key2;                                  
                sorta key1;                                  
                *inlr = *on;
                After the first SORTA:
                Code:
                &gt; EVAL info                                        
                  INFO OF DS(1) = 'key1e     key2a     elem 10   '  
                  INFO OF DS(2) = 'key1b     key2b     elem 8    '  
                  INFO OF DS(3) = 'key1b     key2c     elem 7    '  
                  INFO OF DS(4) = 'key1b     key2d     elem 5    '  
                  INFO OF DS(5) = 'key1b     key2e     elem 3    '  
                  INFO OF DS(6) = 'key1c     key2f     elem 2    '  
                  INFO OF DS(7) = 'key1a     key2g     elem 1    '  
                  INFO OF DS(8) = 'key1d     key2h     elem 6    '  
                  INFO OF DS(9) = 'key1a     key2i     elem 4    '  
                  INFO OF DS(10)= 'key1e     key2j     elem 9    '
                After the second SORTA:
                Code:
                &gt; EVAL info                                          
                  INFO OF DS(1) = 'key1a     key2g     elem 1    '    
                  INFO OF DS(2) = 'key1a     key2i     elem 4    '    
                  INFO OF DS(3) = 'key1b     key2b     elem 8    '    
                  INFO OF DS(4) = 'key1b     key2d     elem 5    '    
                  INFO OF DS(5) = 'key1b     key2e     elem 3    '    
                  INFO OF DS(6) = 'key1b     key2c     elem 7    '  <--- out of order
                  INFO OF DS(7) = 'key1c     key2f     elem 2    '    
                  INFO OF DS(8) = 'key1d     key2h     elem 6    '    
                  INFO OF DS(9) = 'key1e     key2a     elem 10   '    
                  INFO OF DS(10)= 'key1e     key2j     elem 9    '

                Comment


                • #9
                  Sorry about the duplicate post. I got an error the first time. I don't see any way to delete a post.

                  Comment


                  • #10
                    hmm, interesting... not sure why I thought it was stable? QSort is definitely the better option, then.

                    Comment


                    • #11
                      Many years ago I solved this issue for myself by writing a subroutine to sort my DS, with my own sort code using the bubble sort method. I do not recommend that, bubble sort is one of the most inefficient search algorithms there is. QSort is better in every way, if I had known about it then I would have used it.

                      Comment

                      Working...
                      X