Sort list of records by values of keys

Hi, all.

The following script returns occurrences of each word contained by provided text.
The result is list of records. Here it is for given in the script bellow text :


-- RESULT ---> {sample:1, code:1, Catalina:1, pass:1, |preferences|:1, going:1, |by|:1, only:1, |no|:1, |and|:3, such:1, |class|:1, cases:1, |get|:1, |if|:1, because:1, adding:1, |open|:2, |rest|:1, |events|:3, seem:2, There:1, be:2, |above|:1, prompt:1, can:1, deal:1, |doesn't|:1, able:1, |around|:1, background:1, |app|:1, a:2, nowhere:1, |that's|:1, You:1, image:1, |aliases|:1, appears:1, |in|:1, |may|:1, value:1, Access:1, issue:1, |>|:2, Disk:1, |full|:1, |the|:1, |second|:1, |script|:1, works:1, returns:1, Privacy:2, |is|:3, furl:1, |in|:1, so:1, |it|:1, |first|:1, command:2, depending:1, goes:1, |to|:6, permission:1, You:2, |reference|:1, |that|:1, System:1, |file|:2, |of|:1, However:1, |read|:1, Security:1, Presumably:1, issues:1, two:1, image:3, |with|:2, |where|:1, missing:1, this:1, need:1, |the|:7}

What I want, is to sort this list by values of keys, in descending order.

Any idea?


use scripting additions
use framework "Foundation"

set aText to "There seem to be two issues with Image Events and Catalina. 
First, it doesn't seem to be able to deal with aliases.
In the sample code above, the open command returns missing value,
 so the rest of the script goes nowhere. However,
 if you pass a file reference -- «class furl» -- the open command works.

The second issue is that, depending where the image is,
 you may need permission to read the file, and in such cases no prompt appears.
 Presumably that's because Image Events is a background-only app.
 You can get around this by going to System Preferences -> Security & Privacy -> Privacy
 and adding Image Events to Full Disk Access."

set aList to words of aText
set aDictionary to current application's NSMutableDictionary's dictionary()
set aSet to current application's NSCountedSet's setWithArray:aList
set anEnumerator to aSet's objectEnumerator()

repeat
	set aKey to anEnumerator's nextObject()
	if aKey = missing value then exit repeat
	aDictionary's setObject:(aSet's countForObject:aKey) forKey:aKey
end repeat

--aDictionary's keysSortedByValueUsingComparator:{"compare:"} -- Here I need help

set aDictionary to aDictionary as record

No, it’s a single record. So it’s not clear what you want, because dictionaries/records are not ordered by definition.

Yes, now I see that I am going the wrong way. Actually, I would like to have the most effective script for counting word’s occurrences in the given text, in an ordered manner. As I see now, it should be one list of lists as result. Like this:

{{“the”, 7}, {“to”, 6}, and so on}

Is this closer to what you want?

set aList to words of aText
set anArray to current application's NSMutableArray's array()
set aSet to current application's NSCountedSet's setWithArray:aList

repeat with anObject in aSet's allObjects()
	(anArray's addObject:(current application's NSDictionary's dictionaryWithObjects:{anObject, (aSet's countForObject:anObject)} forKeys:{"theWord", "theCount"}))
end repeat

anArray's sortUsingDescriptors:{current application's NSSortDescriptor's sortDescriptorWithKey:"theCount" ascending:false, current application's NSSortDescriptor's sortDescriptorWithKey:"theWord" ascending:true selector:"localizedCaseInsensitiveCompare:"}

anArray as list

Yes, Shane. This is exactly what I need, and thank you very much for that. I will rewrite the entire script. For future generations, so to speak :slight_smile: :


use scripting additions
use framework "Foundation"
property |⌘| : a reference to current application
property NSMutableArray : a reference to NSMutableArray of |⌘|
property NSCountedSet : a reference to NSCountedSet of |⌘|
property NSDictionary : a reference to NSDictionary of |⌘|
property NSSortDescriptor : a reference to NSSortDescriptor of |⌘|

set aText to "There seem to be two issues with Image Events and Catalina. 
First, it doesn't seem to be able to deal with aliases.
In the sample code above, the open command returns missing value,
 so the rest of the script goes nowhere. However,
 if you pass a file reference -- «class furl» -- the open command works.

The second issue is that, depending where the image is,
 you may need permission to read the file, and in such cases no prompt appears.
 Presumably that's because Image Events is a background-only app.
 You can get around this by going to System Preferences -> Security & Privacy -> Privacy
 and adding Image Events to Full Disk Access."

set aList to words of aText
set anArray to NSMutableArray's array()
set aSet to NSCountedSet's setWithArray:aList

repeat with anObject in aSet's allObjects()
	set theObjects to {anObject, (aSet's countForObject:anObject)}
	set theKeys to {"aWord", "aCount"}
	(anArray's addObject:(NSDictionary's dictionaryWithObjects:theObjects forKeys:theKeys))
end repeat

set descriptorOne to NSSortDescriptor's sortDescriptorWithKey:"aCount" ascending:false
set descriptorTwo to NSSortDescriptor's sortDescriptorWithKey:"aWord" ascending:true ¬
	selector:"localizedCaseInsensitiveCompare:"
anArray's sortUsingDescriptors:{descriptorOne, descriptorTwo}

anArray as list