Sorting lists in a list using AppleScriptObjC

Hi,

i know how to sort that listOfLists below by choosen parameters (sort by “p1” then by “p2”), thanks to Shane Stanley:
set listOfLists to {{p1:“a”, p2:“b”}, {p1:“b”, p2:“b”}, {p1:“a”, p2:“a”}, {p1:“b”, p2:“a”}}

But how do i sort that same listOfLists without labeled parameters, just by referencing indexes (sort by items of index 1 then by items of index 2)?
set listOfLists to {{“a”, “b”}, {“b”, “b”}, {“a”, “a”}, {“b”, “a”}}

Thanks for your help!
Vincent

Model: MacBook Pro
Browser: Version 66.0.3359.139
Operating System: Mac OS X (10.11.6)

Hi.

Welcome to MacScripter.

I don’t think it’s possible to sort lists of lists with ASObjC. But it’s easy with vanilla AppleScript if the lists are AppleScript lists containing AppleScript objects and you use a customisable sort like the one here. (The code in the other post is overkill for just four lists, but it works and you won’t see it if it’s used as a library script.) If you compile and save the other script in a folder called “Script Libraries” in your user “Library” folder, you can use it to sort the list of lists with a script like this:

-- Load the script with the sort code, assumed here to have been saved in /Users/username/Library/Script Libraries/ under the name "Custom Iterative Dual-pivot Quicksort.scpt".
use sorter : script "Custom Iterative Dual-pivot Quicksort"
use scripting additions

-- A script object containing a custom comparison handler.
script onItem1ThenOnItem2
	-- Return 'true' if list a's first item is greater than list b's or if the first items are equal and list a's second item is greater than list b's. Return false otherwise.
	on isGreater(a, b)
		set a1 to item 1 of a
		set b1 to item 1 of b
		if (a1 = b1) then
			return (item 2 of a > item 2 of b)
		else
			return (a1 > b1)
		end if
		
	end isGreater
end script

set listOfLists to {{"a", "b"}, {"b", "b"}, {"a", "a"}, {"b", "a"}}

-- Sort items 1 thru -1 of listOfLists, in place, using the comparison handler in the script object above.
tell sorter to sort(listOfLists, 1, -1, {comparer:onItem1ThenOnItem2})
return listOfLists

Or a more flexible usage — allowing the sort-on indices and sort directions to be specified as parameters — would be this, which is similar to a handler I use to sort rows taken from Numbers:

use AppleScript version "2.3.1" -- Mac OS 10.9 (Mavericks) or higher.
-- Load the script with the sort code, assumed here to have been saved in /Users/username/Library/Script Libraries/ under the name "Custom Iterative Dual-pivot Quicksort.scpt".
use sorter : script "Custom Iterative Dual-pivot Quicksort"
use scripting additions

on sortListOfLists(listOfLists, rangeIndex1, rangeIndex2, sortColumnSpecs)
	script o
		property sortColumnIndices : {}
		property sortColumnAscendings : {}
		property sortColumnCount : (count sortColumnSpecs)
		
		on isGreater(a, b) -- a and b are two lists from a list of lists.
			-- Work through the column indices in turn, comparing the indexed values in the two lists until the "greater" list is established.
			repeat with i from 1 to sortColumnCount
				set columnIndex to my sortColumnIndices's item i
				set itemFromA to a's item columnIndex
				set itemFromB to b's item columnIndex
				-- The first non-equal comparison result (if any) decides which list is "greater".
				if (itemFromA = itemFromB) then
				else if (my sortColumnAscendings's item i) then
					return (itemFromA > itemFromB)
				else
					return (itemFromB > itemFromA)
				end if
				-- Continue while no decision and indices remaining.
			end repeat
			
			return false -- All the compared values tested equal, so a is not "greater" than b.
		end isGreater
	end script
	
	-- The sort columns may have been specified either as integers or as records with 'column' and (optionally) 'ascending' properties. Massage the data into the record form. Sort directions are ascending except where explicitly specified otherwise.
	repeat with i from 1 to o's sortColumnCount
		set columnSpec to item i of sortColumnSpecs
		if (columnSpec's class is integer) then
			set end of o's sortColumnIndices to columnSpec
			set end of o's sortColumnAscendings to true
		else if (columnSpec's class is record) then
			set {column:end of o's sortColumnIndices, ascending:end of o's sortColumnAscendings} to columnSpec & {ascending:true}
		else
			error
		end if
	end repeat
	
	tell sorter to sort(listOfLists, rangeIndex1, rangeIndex2, {comparer:o})
end sortListOfLists

set listOfLists to {}
set chars to "abcdefgh"
repeat 10 times
	set end of listOfLists to {some character of chars, some character of chars, some character of chars, some character of chars}
end repeat

-- Sort items 1 thru -1 of listOfLists, sorting on those list's first items (ascending), with descending subsorts on their third items and ascending sub-subsorts on their second items.
-- The individual sort columns may be specified either as integers or records, as here. Sort directions are ascending unless specified otherwise.
set sortColumnSpecs to {1, {column:3, ascending:false}, {column:2}}
sortListOfLists(listOfLists, 1, -1, sortColumnSpecs)
listOfLists

Edit: Minor corrections and speed improvements.