First of all I'm a newbie on oo programming, please have that in mind if you 
want to comment my effort below.
I have written a sort class which will use chained comparators (up to 9  
sortkeys possible )
I would like some feedback on:
What I should have been done different or simpler.
I also need some suggestion on the method names, that will get datainput, 
should have.
For now I use these names:
These two methods will return the sorted fields index in the original array 
Method build  (works the same as Method lines)
Method lines
 
Method append (will return an new array when sort is finnished)
 
All feedback is welcome and explain so also unexperienced and not native 
english speaking oo programmer understand.
Thanks
Håkan
-----------------------------------------------------------------
/*
Say "USEAGE:"
Say "Upto 9 sortfields (sortkeys) can be specified
Say "Setup sortcolumns start,length,(A)sc/(D)esc,(C)ase dependent, caseless if 
empty, default is caseless"
Say "sortrecords  = .Sortrecord~new()"
Say "sortfields   = .array~new"
say "sortfields~append('20,8')       most significant (ascending and caseless 
used as default)"
say "sortfields~append('9,8,d')      second most significant (caseless as 
deafult)"
SAY "sortfields~append('1,8,A,c')    third most significany  ascending and 
casesensitive"
SAY "                                Note all sortfields that pass test as 
being numeric is compared as numeric "
say " "
say "Sortrecords~Sortfields(sortfields)  -- send over the sortfields"
say
Say "Feed array to sort with sortrecords~lines or ~build (works the same)"
say " "
SAY "do item over array                if using a sparse array record index 
must be supplied"
SAY "         Sortrecord~build(item)           ~build(item,array~index(item))  
very slow on big arrays"
Say "end         "
Say " "
Say "-- Sort will return the record nr, fetch record with array~at(seq) "
Say "do seq over Sortrecords~sort     -- Sortrecords~stablesort also available"
Say "    say array~at(seq)"
Say "end"
  Alternate is to ask to get an complete new array back (will solve sparse 
arrays problem) but will use more memory 
  (1 copy of source array) 
  But if the input is from a file directly feeded to sortrecords there is only 
one copy
  Do item over array                 or   do until f~lines() = 0
           sortrecord~append(item)                sortrecord~append(f~linein)   
  end                                     end
  sortrecord~sort                         sortrecord~stablesort
  do item over sortrecord                 do item over sortrecord
           ? whatever                              ? whatever
  end                                     end         
**/
/*
Manage ca 150000  records with 3 sortfields(13 char total length),
 but actual datalength of the records can be bigger 
as this only build what is needed for sorting, returned is the 
index in original array 
 
Manage > 150000 records occasionally, running sortprogram twice 
in a row sometimes the intepreter crash, sometimes interpreter 
just sits there(no CPU) and sometimes it works.
 
This on windows 10 Intel i7 2.67 Ghz 16Gb memory and ooRexx 4.3.0, 
 
*/
::CLASS SortRecord public
 
/***************************************************/
/*                                                 */
/***************************************************/
::method init
expose sortfields  recid sortarray inrecords delim
 
recid      = 0
sortarray  = .array~new(100000)
inrecords  = .array~new(100000)
delim      = '00'x
self~wantArray = .false
/***************************************************/
/*                                                 */
/***************************************************/
::Method sortfields
expose sortfields
use strict arg sortfields
/***************************************************/
/*                                                 */
/***************************************************/
::Method build
expose sortfields sortArray recid delim
use strict arg inrec, rid=''
self~lines(inrec,rid)
/***************************************************/
/*                                                 */
/***************************************************/
::Method lines
expose sortfields sortArray recid delim
use strict arg inrec, rid=''
if rid = '' then
   recid +=1
 else
          recid = rid
  sortstring = ''
  do sf over sortfields
    parse var sf fs ',' fe ',' .
    sortstring = sortstring ||inrec~substr(fs~abs,fe~abs,' 
')~translate('01'x,'20'x) || delim -- '00'x 
  end
 
  parse var sortstring k1 (delim) k2 (delim) k3 (delim) k4 (delim) k5 (delim) 
k6 (delim) k7 (delim) k8 (delim) k9 (delim) .
  Sortarray~append(.sortkeys~new(recid,k1,k2,k3,k4,k5,k6,k7,k8,k9))
 
/***************************************************/
/*                                                 */
/***************************************************/
::Attribute wantArray
::Method append
expose sortfields sortArray recid inrecords delim
use strict arg inrec, rid=''
 
  inrecords~append(inrec)
  if \ self~wantArray then self~wantArray = .true 
          
  self~lines(inrec,rid)        
/***************************************************/
/*                                                 */
/***************************************************/
::Method Sortchain private
expose sortarray inrecords sortfields delim chain
kseq. = ''
ci.   = ''
f.    = ''
do sf over sortfields
 parse var sf fs ',' fe ',' seq ',' CI .
   x       = sortfields~index(sf)
   kseq.x  = seq~translate
   ci.x    = ci~translate
   f.x     = fe
end
 
k1 = .Sortkey1~new(kseq.1,ci.1)
k2 = .Sortkey2~new(kseq.2,ci.2)
k3 = .Sortkey3~new(kseq.3,ci.3)
k4 = .Sortkey4~new(kseq.4,ci.4)
k5 = .Sortkey5~new(kseq.5,ci.5)
k6 = .Sortkey6~new(kseq.6,ci.6)
k7 = .Sortkey7~new(kseq.7,ci.7)
k8 = .Sortkey8~new(kseq.8,ci.8)
k9 = .Sortkey9~new(kseq.9,ci.9)
 
chain7 = .chaincomparator~new(k8,k9)
chain6 = .chaincomparator~new(k7,chain7)
chain5 = .chaincomparator~new(k6,chain6)
chain4 = .chaincomparator~new(k5,chain5)
chain3 = .chaincomparator~new(k4,chain4)
chain2 = .chaincomparator~new(k3,chain3)
chain1 = .chaincomparator~new(k2,chain2)
chain  = .chaincomparator~new(k1,chain1)
       
     if sortfields~items = 1 then do 
               --chain  = .chaincomparator~new(k1,k1)
               chain  = k1
     end         
     if sortfields~items = 2 then do
        chain  = .chaincomparator~new(k1,k2)
     end         
     if sortfields~items = 3 then do
        chain1 = .chaincomparator~new(k2,k3)
     end         
     if sortfields~items = 4 then do
        chain2 = .chaincomparator~new(k3,k4)
     end         
     if sortfields~items = 5 then do
                chain3 = .chaincomparator~new(k4,k5)
     end
     if sortfields~items = 6 then do
                chain4 = .chaincomparator~new(k5,k6)
     end
     if sortfields~items = 7 then do
                chain5 = .chaincomparator~new(k6,k7)
     end
     if sortfields~items = 8 then do
                chain6 = .chaincomparator~new(k7,k8)
     end
     if sortfields~items = 9 then do
                chain7 = .chaincomparator~new(k8,k9)
     end
 
/***************************************************/
/*                                                 */
/***************************************************/               
::Method sort
expose sortarray chain inrecords
 
self~sortchain
sortarray~sortwith(chain)
if self~wantArray then do 
 z = .array~new(sortarray~items) 
 do item over sortarray
           z~append(inrecords~at(item))
 end          
return z
end
 
return sortarray
 
/***************************************************/
/*                                                 */
/***************************************************/
::Method stablesort
expose sortarray chain inrecords
 
self~sortchain
sortarray~stablesortwith(chain)
 
if self~wantArray then do 
 z = .array~new(sortarray~items) 
 do item over sortarray
           z~append(inrecords~at(item))
 end          
return z
end
 
 
return sortarray
 
/***************************************************/
/*                                                 */
/***************************************************/
::Class sortKeys private
/***************************************************/
/*                                                 */
/***************************************************/
::Method Init
expose recid key1 key2 key3 key4 key5 key6 key7 key8 key9
use arg recid, key1='' , key2='' , key3='' , key4='' , key5='', key6='', 
key7='', key8='', key9=''
 
::Attribute key1
::Attribute key2
::Attribute key3
::Attribute key4
::Attribute key5
::Attribute key6
::Attribute key7
::Attribute key8
::Attribute key9
::Attribute recid
/***************************************************/
/*                                                 */
/***************************************************/
::Method string
expose recid
return recid
 
/***************************************************/
/*                                                 */
/***************************************************/
--Here is a simple one.
--The two arguments are comparators that determine how to compare the primary 
and secondary fields.
--The secondary, of course, can be another chain comparator if you wish to go 
deeper.
--Thanks to Rick McGuire on REXXLA list 23 jan 2014
-- For CLASS chaincomparator
 
::class chaincomparator private
/***************************************************/
/*                                                 */
/***************************************************/
::method init
  expose primary secondary
  use strict arg primary, secondary
/***************************************************/
/*                                                 */
/***************************************************/
::method compare
  expose primary secondary
  use strict arg first, second
 
  res = primary~compare(first, second)
 
  if res = 0 then res = secondary~compare(first, second)
 
  return res
-- Ricks code stops here --  
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey1 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose sort case
use strict arg left, right
 
if left~key1~datatype('N') & right~key1~datatype('N') then
            return sort*(left~key1-right~key1)~sign  
                 
   if case then
      return sort*left~key1~compareTo(right~key1)
    else
      return sort*left~key1~caselesscompareTo(right~key1)
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey2 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~key2~datatype('N') & right~key2~datatype('N') then
            return sort*(left~key2-right~key2)~sign
 
  if case then
      return sort*left~key2~compareTo(right~key2)
    else
      return sort*left~key2~caselesscompareTo(right~key2)
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey3 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~Key3~datatype('N') & right~Key3~datatype('N') then
            return sort*(left~Key3-right~Key3)~sign
 
  if case then
      return sort*left~Key3~compareTo(right~Key3)
    else
      return sort*left~Key3~caselesscompareTo(right~Key3)
 
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey4 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~Key4~datatype('N') & right~Key4~datatype('N') then
            return sort*(left~Key4-right~Key4)~sign
 
  if case then
      return sort*left~Key4~compareTo(right~Key4)
    else
      return sort*left~Key4~caselesscompareTo(right~Key4)
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey5 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~Key5~datatype('N') & right~Key5~datatype('N') then
            return sort*(left~Key5-right~Key5)~sign
 
  if case then
      return sort*left~Key5~compareTo(right~Key5)
    else
      return sort*left~Key5~caselesscompareTo(right~Key5)
      
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey6 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~Key6~datatype('N') & right~Key6~datatype('N') then
            return sort*(left~Key6-right~Key6)~sign
 
  if case then
      return sort*left~Key6~compareTo(right~Key6)
    else
      return sort*left~Key6~caselesscompareTo(right~Key6)
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey7 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~Key7~datatype('N') & right~Key7~datatype('N') then
            return sort*(left~Key7-right~Key7)~sign
 
  if case then
      return sort*left~Key7~compareTo(right~Key7)
    else
      return sort*left~Key7~caselesscompareTo(right~Key7)
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey8 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~Key8~datatype('N') & right~Key8~datatype('N') then
            return sort*(left~Key8-right~Key8)~sign
 
  if case then
      return sort*left~Key8~compareTo(right~Key8)
    else
      return sort*left~Key8~caselesscompareTo(right~Key8)
/***************************************************/
/*                                                 */
/***************************************************/
::CLASS SortKey9 MIXINCLASS 'Comparator' private
::ATTRIBUTE sort
::Attribute  case
/***************************************************/
/*                                                 */
/***************************************************/
::Method init
  expose sort case
  use arg seq, ci ='I'
  sort = 1
  case = .false
  if seq~translate = 'D' then sort = -1
  if ci~translate  = 'C' then case = .true
/***************************************************/
/*                                                 */
/***************************************************/
::METHOD compare
  expose  sort case
use strict arg left, right
 
if left~Key9~datatype('N') & right~Key9~datatype('N') then
            return sort*(left~Key9-right~Key9)~sign
 
  if case then
      return sort*left~Key9~compareTo(right~Key9)
    else
      return sort*left~Key9~caselesscompareTo(right~Key9)      
------------------------------------------------------------------------------
_______________________________________________
Oorexx-users mailing list
Oorexx-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-users

Reply via email to