I thought I would do a quick review of sort handlers which are intended for use with relatively small lists. The main criteria in this review were speed and code brevity, and my test list contained 100 items:
set theList to {"mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa", "mm", "cc", "xx", "oo", "aa"}
The following ASObjC script performed the sort in 1 millisecond (with the Foundation framework in memory) and only required two lines of code. I include this script primarily to set a benchmark, because my main interest is sort routines that employ basic AppleScript.
use framework "Foundation"
use scripting additions
set sortedList to getSortedList(theList)
on getSortedList(theList)
set theArray to current application's NSArray's arrayWithArray:theList
return (theArray's sortedArrayUsingSelector:"localizedStandardCompare:") as list
end getSortedList
Second place went to the shell, which took 5 milliseconds and required 5 lines of code. This approach is also very fast when used with extremely large lists and is competitive with ASObjC in this regard. However, it returns an unexpected result in rare cases when a case-insensitive sort is done (the -f option).
set sortedList to getSortedList(theList)
on getSortedList(theList)
set {TID, text item delimiters} to {text item delimiters, linefeed}
set theText to theList as text
set sortedList to paragraphs of (do shell script "echo " & quoted form of theText & " | sort -f")
set text item delimiters to TID
return sortedList
end getSortedList
Third place went to a bubble sort enhanced with a script object. It took 9 milliseconds and required 9 lines of code:
set sortedList to getSortedList(theList)
on getSortedList(theList)
script o
property a : theList
end script
repeat with i from (count o's a) to 2 by -1
repeat with j from 1 to i - 1
if item j of o's a > item (j + 1) of o's a then set {item j of o's a, item (j + 1) of o's a} to {item (j + 1) of o's a, item j of o's a}
end repeat
end repeat
return o's a
end getSortedList
Next came QSort which only took 5 milliseconds but contained 17 lines of code. I’m not certain of the author of this script (Nigel perhaps):
set sortedList to Qsort(theList, 1, (count theList))
on Qsort(theList, leftEnd, rightEnd)
set {i, j} to {leftEnd, rightEnd}
set v to item ((leftEnd + rightEnd) div 2) of theList
repeat while (j > i)
repeat while (item i of theList < v)
set i to i + 1
end repeat
repeat while (item j of theList > v)
set j to j - 1
end repeat
if (not i > j) then
set {item i of theList, item j of theList} to {item j of theList, item i of theList}
set {i, j} to {i + 1, j - 1}
end if
end repeat
if (leftEnd < j) then Qsort(theList, leftEnd, j)
if (rightEnd > i) then Qsort(theList, i, rightEnd)
return theList
end Qsort
Last was bubble sort, which took 31 milliseconds and contained 6 lines of code. This approach should not be rejected out of hand, because it only required one-half of one millisecond to sort a list of 20 items.
set sortedList to getSortedList(theList)
on getSortedList(a)
repeat with i from (count a) to 2 by -1
repeat with j from 1 to i - 1
if item j of a > item (j + 1) of a then set {item j of a, item (j + 1) of a} to {item (j + 1) of a, item j of a}
end repeat
end repeat
return a
end getSortedList
All of the timing tests were done on my 2023 Mac mini with Script Geek.