is this even possible?...
Last Post 21 Mar 2007 05:25 PM by Jeff Davis. 12 Replies.
AddThis - Bookmarking and Sharing Button Printer Friendly
  •  
  •  
  •  
  •  
  •  
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Author Messages Not Resolved
Shane Cessna
New Member
New Member
Posts:4
Avatar

--
19 Mar 2007 02:49 PM
is there a way to sort the following qualified DS array by more than one field at the same time? for example if I want to sort this by tisec1, then by tisec2, how do I do it?...

d                 ds                                         
d temp                          63a   dim(30000)             
d  tiempn                        9p 0 inz overlay(temp:1)    
d  tisec1                       10a   inz overlay(temp:*next)
d  tisec2                       10a   inz overlay(temp:*next)
d  tisec3                       10a   inz overlay(temp:*next)
d  tiretm                        5p 2 inz overlay(temp:*next)
d  tisetm                        5p 2 inz overlay(temp:*next)
d  tisced                        3a   inz overlay(temp:*next)
d  tidown                        1p 0 inz overlay(temp:*next)
d  tidlnt                        5p 2 inz overlay(temp:*next)
Shane
J Taylor
Senior Member
Senior Member
Posts:4007

--
19 Mar 2007 02:51 PM Accepted Answer
Posting code
Tommy Holden
Senior Member
Senior Member
Posts:2833
Avatar

--
19 Mar 2007 03:04 PM Accepted Answer
is there a way to sort the following qualified DS array by more than one field at the same time?
This isn't really a qualified DS. A qualified DS is a named DS with the keyword QUALIFIED on the DS line:
 
it's just a standard DS with an array as a subfield.
<blockquote>
for example if I want to sort this by tisec1, then by tisec2, how do I do it?...

[CODE]
d                 ds                                         
d temp                          63a   dim(30000)             
d  tiempn                        9p 0 inz overlay(temp:1)    
d  tisec1                       10a   inz overlay(temp:*next)
d  tisec2                       10a   inz overlay(temp:*next)
d  tisec3                       10a   inz overlay(temp:*next)
d  tiretm                        5p 2 inz overlay(temp:*next)
d  tisetm                        5p 2 inz overlay(temp:*next)
d  tisced                        3a   inz overlay(temp:*next)
d  tidown                        1p 0 inz overlay(temp:*next)
d  tidlnt                        5p 2 inz overlay(temp:*next)
Shane Kronos....sigh... to answer the question, not in the fashion you are using the DS Array. What exactly are you trying to accomplish? You should be able to do sorting using the QSORT api or similar. (you can do a forum search for QSORT for more info. never used it but seems like a likely candidate) My gut feel is that what you are trying to achieve may have a simpler alternative than you are using.
Tommy Holden
Senior Member
Senior Member
Posts:2833
Avatar

--
19 Mar 2007 03:31 PM Accepted Answer
this seems to work for me (i changed it to use the employee master due to data...)

     hoption(*nodebugio)
     Fckempeff  IF   E           K DISK
     d                 ds
     d temp                          36a   dim(10)
     d teeempn                        9p 0 inz overlay(temp:1)
     d teesec3                       10a   inz overlay(temp:*next)
     d teesec4                       10a   inz overlay(temp:*next)
     d teesec5                       10a   inz overlay(temp:*next)
     d i               s             10i 0

      /free
         for i = 1 to 10;
           read ckempeff;
           if %eof;
             leave;
           endif;

           teeempn(i)=eeempn;
           teesec3(i)=eesec3;
           teesec4(i)=eesec4;
           teesec5(i)=eesec5;
         endfor;
         sorta teesec3;
         sorta teesec4;
         *inlr=*on;
         return;
that should get it for you.
Jeff Davis
Basic Member
Basic Member
Posts:68

--
19 Mar 2007 04:33 PM Accepted Answer
Use the QSORT API. This will allow you to sort the data structure anyway you want. Scott Klement wrote some atricles on the ise of QSORT. But here is an example.


H DFTACTGRP(*NO) BNDDIR('QC2LE')

D qsort           PR                  ExtProc('qsort')
D   base                          *   value
D   num                         10U 0 value
D   width                       10U 0 value
D   compare                       *   procptr value

D SortMethod PR            10I 0
D   parm1                             like(sort)
D   parm2                             like(sort)

D Sort             DS                                         
D temp                          63a   dim(30000)             
D  tiempn                        9p 0 inz overlay(temp:1)    
D  tisec1                       10a   inz overlay(temp:*next)
D  tisec2                       10a   inz overlay(temp:*next)
D  tisec3                       10a   inz overlay(temp:*next)
D  tiretm                        5p 2 inz overlay(temp:*next)
D  tisetm                        5p 2 inz overlay(temp:*next)
D  tisced                        3a   inz overlay(temp:*next)
D  tidown                        1p 0 inz overlay(temp:*next)
D  tidlnt                        5p 2 inz overlay(temp:*next)

D num_elemets     s             10I 0

  * Num_Elemets is the number of elements loaded in the array

C                   callp     qsort(%addr(Sort): num_elemets:
C                                   %size(Sort): %paddr('SORTMETHOD'))
C                   eval      *inlr = *on

P SortMethod      B
D SortMethod      PI            10I 0
D   parm1                             like(sort)
D   parm2                             like(sort)

C                   select
C                   when      parm1.Tisec1 < parm2.Tisec.1
C                   return    -1
C                   when      parm1.Tisec1 > parm2.Tisec.2
C                   return    1
C                   when      parm1.Tisec1 = parm2.Tisec.1 and
C                                  parm1.Tisec2 < parm2.Tisec.2
C                   return    -1
C                   when      parm1.Tisec1 = parm2.Tisec.2 and
C                                  parm1.Tisec2 > parm2.Tisec.2
C                   return    1
C                   other
C                   return    0
C                   endsl

P                 E  

This is not tested but just an example of how it could be done. I would refer to Scott's articles for more information.
Bob Genis
Basic Member
Basic Member
Posts:151

--
19 Mar 2007 06:53 PM Accepted Answer
For multiple sorts, I'd extend the above to be something like this.


P SortMethod      B
D SortMethod      PI            10I 0
D   parm1                             like(sort)
D   parm2                             like(sort)

C                   select
C                   when      parm1.Tisec1 < parm2.Tisec1
C                   return    -1
C                   when      parm1.Tisec1 > parm2.Tisec1
C                   return    1
C                   when      parm1.Tisec1 = parm2.Tisec1 
C                   return    SortMethod2(parm1:parm2)
C                   endsl

P                 E  

P SortMethod2     B
D SortMethod2     PI            10I 0
D   parm1                             like(sort)
D   parm2                             like(sort)

C                   select
C                   when      parm1.Tisec2 < parm2.Tisec2
C                   return    -1
C                   when      parm1.Tisec2 > parm2.Tisec2
C                   return    1
C                   when      parm1.Tisec2 = parm2.Tisec2 
C                   return    0
C                   endsl

P                 E  
Separating out the levels improves readability. If you specify a global parameter for sort order, you could add/rearrange the various sort levels. The "equal" condition always just returns the result of the next sort level until you get to the bottom of the tree.
Bryan Leaman
Veteran Member
Veteran Member
Posts:1745
Avatar

--
19 Mar 2007 07:52 PM Accepted Answer
qsort is the most flexible method, but in this specific case, if you only care about sorting by contiguous array elements, just create a dummy array over the other two...
d temp                          63a   dim(30000)             
d  tiempn                        9p 0 inz overlay(temp:1)    
d  tisec1                       10a   inz overlay(temp:*next)
d  tisec2                       10a   inz overlay(temp:*next)
d  tisec3                       10a   inz overlay(temp:*next)
d  tiretm                        5p 2 inz overlay(temp:*next)
d  tisetm                        5p 2 inz overlay(temp:*next)
d  tisced                        3a   inz overlay(temp:*next)
d  tidown                        1p 0 inz overlay(temp:*next)
d  tidlnt                        5p 2 inz overlay(temp:*next)
d  sortby                       20a   overlay(temp:6)
  /free
    SORTA  sortby;
  /end-free
--Bryan
Barbara Morris
Senior Member
Senior Member
Posts:5220

--
19 Mar 2007 08:57 PM Accepted Answer
this seems to work for me (i changed it to use the employee master due to data...)

that should get it for you.</blockquote>

Tommy, unfortunately, RPG's SORTA doesn't preserve the existing order for elements that have the same sort value.

(I agree that sorting with qsort() is probably the easiest way to sort by multiple keys.)

See the little program below that illustrates that SORTA can't be used to sort by multiple keys.  The DSPLY results show that the initial sort by "subtype" was lost during the second sort by "type". 
[CODE]
DSPLY  initial arr  <a1 b3 a4 d2 a7 c2 a8 a9 b2 a6 >
DSPLY  sort subtype <a1 c2 d2 b2 b3 a4 a6 a7 a8 a9 >
DSPLY  sort type    <a1 a7 a4 a6 a8 a9 b3 b2 c2 d2 >

     D ds              ds
     D   arr                               dim(10) ctdata perrcd(10)
     D    type                        1a   overlay(arr:*next)
     D    subtype                     1a   overlay(arr:*next)
     D    filler                      1a   overlay(arr:*next)
      /free
         dsply ('initial arr  <' + ds + '>');
         sorta subtype;
         dsply ('sort subtype <' + ds + '>');
         sorta type;
         dsply ('sort type    <' + ds + '>');
         *inlr = '1';
      /end-free
**CTDATA arr
a1 b3 a4 d2 a7 c2 a8 a9 b2 a6
Barbara Morris
Senior Member
Senior Member
Posts:5220

--
19 Mar 2007 09:07 PM Accepted Answer

<i>(I corrected a couple of your subfield names)</i>
C                   select
C                   when      parm1.Tisec1 < parm2.Tisec1
C                   return    -1
C                   when      parm1.Tisec1 > parm2.Tisec1
C                   return    1
C                   when      parm1.Tisec1 = parm2.Tisec1 and
C                                  parm1.Tisec2 < parm2.Tisec2
C                   return    -1
C                   when      parm1.Tisec1 = parm2.Tisec1 and
C                                  parm1.Tisec2 > parm2.Tisec2
C                   return    1
C                   other
C                   return    0
C                   endsl
You can simplify some of the checking here. The WHEN cases are tested in the order they are coded; once you get down to the third WHEN, you know that the Tisec1 subfields are equal, so you don't need to check that in your comparison.

C                   select
 * Compare Tisec1 first
C                   when      parm1.Tisec1 < parm2.Tisec1
C                   return    -1
C                   when      parm1.Tisec1 > parm2.Tisec1
C                   return    1
 * Tisec1 is equal; compare Tisec2 next
C                   when      parm1.Tisec2 < parm2.Tisec2
C                   return    -1
C                   when      parm1.Tisec2 > parm2.Tisec2
C                   return    1
 * Tisec1 and Tisec2 are equal
C                   other
C                   return    0
C                   endsl
Shane Cessna
New Member
New Member
Posts:4
Avatar

--
20 Mar 2007 01:50 PM Accepted Answer
d temp                          63a   dim(30000)             
d  tiempn                        9p 0 inz overlay(temp:1)    
d  tisec1                       10a   inz overlay(temp:*next)
d  tisec2                       10a   inz overlay(temp:*next)
d  tisec3                       10a   inz overlay(temp:*next)
d  tiretm                        5p 2 inz overlay(temp:*next)
d  tisetm                        5p 2 inz overlay(temp:*next)
d  tisced                        3a   inz overlay(temp:*next)
d  tidown                        1p 0 inz overlay(temp:*next)
d  tidlnt                        5p 2 inz overlay(temp:*next)
d  sortby                       20a   overlay(temp:6)
  /free
    SORTA  sortby;
  /end-free
Bryan, Thank you so much for your suggestion...it worked great...:D Shane
Jeff Davis
Basic Member
Basic Member
Posts:68

--
21 Mar 2007 04:43 PM Accepted Answer
Barbara, The only reason I do it that way is when programmers come in behind me. I would hope they understand that is the way the SELECT statment works, but I found out more times then not, they don't. So to cut down on the confussion, I started writing statements like I posted.
Barbara Morris
Senior Member
Senior Member
Posts:5220

--
21 Mar 2007 05:17 PM Accepted Answer
The only reason I do it that way is when programmers come in behind me. I would hope they understand that is the way the SELECT statment works, but I found out more times then not, they don't. So to cut down on the confussion, I started writing statements like I posted.
Hmm. Maybe you should switch to IF and ELSEIF; most programmers would understand how that works. I think coding the unnecessary conditions in your WHEN statements might ultimately increase the confusion. If someone is unfamiliar with SELECT and sees that kind of coding, they might incorrectly deduce that all matching WHEN statements are processed, or that the WHENs are processed in a random order. Your WHEN statements would get pretty complicated as you added more subfields to be compared; even good maintenance programmers might have a hard time with the code. If you have lazy maintenance programmers who don't know the language and won't read the manual, it's probably impossible to guess all the ways they might misunderstand your code. It might be better to add "well-duh" comments than to write awkward code that they still might misunderstand.
Jeff Davis
Basic Member
Basic Member
Posts:68

--
21 Mar 2007 05:25 PM Accepted Answer
Hmmmm...good point. I never thought about it that way. Something to look forward into the future with. Thanks for the insight.
You are not authorized to post a reply.

Acceptable Use Policy