I have a “quick-sort” routine that can sort a list of lists.
It can even sort ascending and descending on a per item basis.
Let me know if you want me to post it?
EDIT - I found it and decided to post it anyways
Enjoy
BTW - Generating the list takes awhile. Sorting is very fast
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on run
set bList to generateListMulti(2048, 3) -- generates a list of lists with 3 items
set sortList to {2, -3} -- list of items to sort by, a negative value means sort descending
-- "2" tells it to sort first by the second item ascending, and "-3" tells it to sub-sort by item 3 descending
quickSortMulti(bList, sortList)
get bList
end run
on generateListMulti(maxCount, numItems)
script mL
property nlist : {}
property glist : {}
end script
repeat numItems times
set end of mL's nlist to 0
end repeat
repeat maxCount times
repeat with i from 1 to numItems
set item i of mL's nlist to random number from 1 to maxCount
end repeat
copy mL's nlist to end of mL's glist
end repeat
return mL's glist
end generateListMulti
on quickSortMulti(alist, sortList) -- Non-Recursive FASTEST
local px, lo, hi, j, L, H, sw, c, comp -- px means 'Pivot Index'
script mL
property nlist : alist
property sList : {}
property oList : {}
property stack : {}
end script
repeat with j in sortList
if j > 0 then -- if positive, sort ascending
set end of mL's sList to (contents of j)
else -- if negative,sort descending
set end of mL's sList to -(contents of j)
end if
set end of mL's oList to (j > 0)
end repeat
set end of mL's stack to {1, count of mL's nlist}
repeat until (count of mL's stack) = 0 --sc
set lo to item 1 of item 1 of mL's stack
set hi to item 2 of item 1 of mL's stack
-- partitionHoare
set px to item ((hi + lo) div 2) of mL's nlist
set L to lo
set H to hi
repeat
set comp to true
repeat while comp
repeat with j from 1 to count of mL's sList -- do multiple comparisons
set c to item j of mL's sList
set comp to false
if item c of item L of mL's nlist < item c of px then
if item j of mL's oList then set comp to true -- ascending
exit repeat
else if item c of item L of mL's nlist > item c of px then
if not (item j of mL's oList) then set comp to true --descending
exit repeat
end if
end repeat
if comp then set L to L + 1
end repeat
set comp to true
repeat while comp
repeat with j from 1 to count of mL's sList -- do multiple comparisons
set c to item j of mL's sList
set comp to false
if item c of item H of mL's nlist > item c of px then
if item j of mL's oList then set comp to true -- ascending
exit repeat
else if item c of item H of mL's nlist < item c of px then
if not (item j of mL's oList) then set comp to true --descending
exit repeat
end if
end repeat
if comp then set H to H - 1
end repeat
if L ≥ H then
exit repeat
end if
set sw to item L of mL's nlist
set item L of mL's nlist to item H of mL's nlist
set item H of mL's nlist to sw
set L to L + 1
set H to H - 1
end repeat
set px to H -- end of partitionHoare
set mL's stack to rest of mL's stack
if px + 1 < hi then
set beginning of mL's stack to {px + 1, hi}
end if
if lo < px then
set beginning of mL's stack to {lo, px}
end if
end repeat
end quickSortMulti
Edit 2 Here is a second version that uses ApplescriptObjC to generate the random numbers for list generation. Much faster.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "GamePlayKit"
on run
set bList to generateListMulti(2048, 3) -- generates a list of lists with 3 items
display alert "List generated." giving up after 1
set sortList to {2, -3} -- list of items to sort by, a negative value means sort descending
-- "2" tells it to sort first by the second item ascending, and "-3" tells it to sub-sort by item 3 descending
quickSortMulti(bList, sortList)
get bList
end run
on generateListMulti(maxCount, numItems)
local randomSource, randItem
script mL
property nlist : {}
property glist : {}
end script
set randomSource to current application's GKRandomSource's alloc()'s init()
set randItem to current application's GKGaussianDistribution's alloc()'s initWithRandomSource:randomSource lowestValue:"1" highestValue:(maxCount as text)
repeat numItems times
set end of mL's nlist to 0
end repeat
repeat maxCount times
repeat with i from 1 to numItems
set item i of mL's nlist to (randItem's nextInt()) as integer
end repeat
copy mL's nlist to end of mL's glist
end repeat
return mL's glist
end generateListMulti
on quickSortMulti(alist, sortList) -- Non-Recursive FASTEST
local px, lo, hi, j, L, H, sw, c, comp -- px means 'Pivot Index'
script mL
property nlist : alist
property sList : {}
property oList : {}
property stack : {}
end script
repeat with j in sortList
if j > 0 then -- if positive, sort ascending
set end of mL's sList to (contents of j)
else -- if negative,sort descending
set end of mL's sList to -(contents of j)
end if
set end of mL's oList to (j > 0)
end repeat
set end of mL's stack to {1, count of mL's nlist}
repeat until (count of mL's stack) = 0 --sc
set lo to item 1 of item 1 of mL's stack
set hi to item 2 of item 1 of mL's stack
-- partitionHoare
set px to item ((hi + lo) div 2) of mL's nlist
set L to lo
set H to hi
repeat
set comp to true
repeat while comp
repeat with j from 1 to count of mL's sList -- do multiple comparisons
set c to item j of mL's sList
set comp to false
if item c of item L of mL's nlist < item c of px then
if item j of mL's oList then set comp to true -- ascending
exit repeat
else if item c of item L of mL's nlist > item c of px then
if not (item j of mL's oList) then set comp to true --descending
exit repeat
end if
end repeat
if comp then set L to L + 1
end repeat
set comp to true
repeat while comp
repeat with j from 1 to count of mL's sList -- do multiple comparisons
set c to item j of mL's sList
set comp to false
if item c of item H of mL's nlist > item c of px then
if item j of mL's oList then set comp to true -- ascending
exit repeat
else if item c of item H of mL's nlist < item c of px then
if not (item j of mL's oList) then set comp to true --descending
exit repeat
end if
end repeat
if comp then set H to H - 1
end repeat
if L ≥ H then
exit repeat
end if
set sw to item L of mL's nlist
set item L of mL's nlist to item H of mL's nlist
set item H of mL's nlist to sw
set L to L + 1
set H to H - 1
end repeat
set px to H -- end of partitionHoare
set mL's stack to rest of mL's stack
if px + 1 < hi then
set beginning of mL's stack to {px + 1, hi}
end if
if lo < px then
set beginning of mL's stack to {lo, px}
end if
end repeat
end quickSortMulti