Hi Nigel,
I executed some test and the “magic” routine is very fast. To sort a list of list of 10,000 item (where each item is composed by string, number and date items) take about 2.5 sec (!!!)
Somebody say: “Nigel is excellent for AppleScript speed. Maybe the best in the world.” I confirm.
Below your complete script with a routine to generate a Tab-Text file useful for test speed.
Thanks again.
property listOfLists : missing value – to speedup the access to list generation using “my” term
– Generate the Tab-Textfile to test
set filePathTest to “Leopard:Users:steve:Desktop:tableTest.txt”
set fileRef to open for access file filePathTest with write permission
set eof of fileRef to 0
repeat with j from 1 to 10000
set filePath to “Macintosh HD:Users:steve:Test:image_” & (random number from 10000 to 90000)
set fileSize to random number from 100000 to 500000
set creationDate to (current date) + (random number from 5000 to 500000)
write (filePath & tab & fileSize & tab & creationDate & return) as «class utf8» to fileRef
end repeat
close access fileRef
– Read the Tab-Text file and convert it into List of List
set fileRef to open for access file filePathTest
set listOfLists to read fileRef using delimiter return as «class utf8»
close access fileRef
repeat with j from 1 to count my listOfLists
set AppleScript’s text item delimiters to tab
set textItemsTmp to text items of item j of my listOfLists
set AppleScript’s text item delimiters to “”
set item 2 of textItemsTmp to (item 2 of textItemsTmp) as integer
set item 3 of textItemsTmp to date (item 3 of textItemsTmp)
set item j of my listOfLists to textItemsTmp
end repeat
set t1 to current date
sortListsByNthItem(listOfLists, 3, 1) – {List, column to sort, flag 1 for ascending, -1 for descending}
set t2 to current date
set t3 to t2 - t1
on sortListsByNthItem(listOfLists, n, direction)
script o – Script object for forward (ascending) sort.
on isGreater(a, b)
(item n of a > item n of b)
end isGreater
on isLess(a, b)
(item n of a < item n of b)
end isLess
-- These two handlers aren't used in the current context,
-- but have to exist to match the calls in CustomQsort.
on swap(i, j)
end swap
on shift(i, j)
end shift
end script
script r -- Script object for reverse (descending) sort.
property parent : o -- Inherit all the properties (inc. handlers) of o.
-- Swap the isGreater and isLess handlers.
property isGreater : o's isLess
property isLess : o's isGreater
end script
CustomQsort(listOfLists, 1, -1, item direction of {o, r})
end sortListsByNthItem
on CustomQsort(theList, l, r, compObj)
script o
property cutoff : 10
property p : theList
on qsrt(l, r)
set i to l
set j to r
set v to my p's item ((l + r) div 2)
repeat while (j > i)
set u to my p's item i
repeat while (compObj's isLess(u, v))
set i to i + 1
set u to my p's item i
end repeat
set w to my p's item j
repeat while (compObj's isGreater(w, v))
set j to j - 1
set w to my p's item j
end repeat
if (i > j) then
else
set my p's item i to w
set my p's item j to u
-- Perform any additional actions that may be required after this swap.
compObj's swap(i, j)
set i to i + 1
set j to j - 1
end if
end repeat
if (j - l < cutoff) then
else
qsrt(l, j)
end if
if (r - i < cutoff) then
else
qsrt(i, r)
end if
end qsrt
on isrt(l, r)
set x to l
set z to l + cutoff - 1
if (z > r) then set z to r
set v to my p's item x
set u to v
repeat with y from (x + 1) to z
tell my p's item y
if (compObj's isLess(it, v)) then
set x to y
set v to it
end if
end tell
end repeat
set my p's item x to u
set my p's item l to v
-- Perform any additional actions that may be required after this swap.
compObj's swap(l, x)
set u to my p's item (l + 1)
repeat with i from (l + 2) to r
set v to my p's item i
if (compObj's isLess(v, u)) then
set my p's item i to u
repeat with j from (i - 2) to l by -1
tell my p's item j
if (compObj's isLess(v, it)) then
set my p's item (j + 1) to it
else
set my p's item (j + 1) to v
-- Perform any additional actions that may be required after this insertion.
compObj's shift(j + 1, i)
exit repeat
end if
end tell
end repeat
else
set u to v
end if
end repeat
end isrt
end script
set listLen to (count theList)
if (listLen > 1) then -- otherwise the handler will error
-- Translate negative indices
if (l < 0) then set l to listLen + l + 1
if (r < 0) then set r to listLen + r + 1
if (r = l) then
-- No point in sorting just one item
else
-- Transpose transposed indices
if (l > r) then
set temp to l
set l to r
set r to temp
end if
if (r - l < o's cutoff) then
-- Skip the Quicksort if cutoff or less items
else
o's qsrt(l, r)
end if
o's isrt(l, r)
end if
end if
return -- nothing
end CustomQsort