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
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-users