So here’s a further development of KniazidisR’s script which acts case-insensitively unless the call to it is in a ‘considering case’ statement. I rather like the idea of returning co-most frequent values in the order and form of their first instances in the original list, so I’ve included the NSOrderedSet idea. The two classes of set seem capable themselves of recognising when integers and reals represent the same values.
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
property |⌘| : a reference to current application
set aList to {"a", "A", "a", 7.0, "B", {x:"HellO"}, "c", 7, 7, {x:"Hello"}, 7, "a", "b", "c", 7, "a", {x:"HELLO"}, "e", "f", 7, {x:"hello"}, "a", "a", 7, 7, "a", "b", {x:"HellO"}, "b", "b", {x:"HeLLo"}, "b", {x:"Hello"}, "b", {x:"Hello"}, "b"}
-- considering case
mostProlificItems(aList)
-- end considering
on mostProlificItems(aList)
set countedSet to |⌘|'s NSCountedSet's alloc()'s initWithArray:aList -- For the occurrence count of each value (distinguished case-sensitively).
set orderedSet to |⌘|'s class "NSOrderedSet"'s orderedSetWithArray:(aList) -- For the first instance of each value (ditto) in the original order.
script o
property listOfValues : orderedSet's array() as list -- The ordered set's contents as a list of AS values
property listOfRecords : {}
property checklist : {}
end script
set checklistLength to 0
repeat with i from 1 to (count o's listOfValues)
set aValue to item i of o's listOfValues
set aCount to (countedSet's countForObject:aValue) as integer
-- Has this value already been handled in another case when case is being ignored?
if (o's checklist contains {aValue}) then
-- If so, get the index of the version in the checklist and update the count in the corresponding record.
repeat with j from 1 to checklistLength
if (item j of o's checklist is aValue) then exit repeat
end repeat
tell item j of o's listOfRecords to set its numberOfTimes to (its numberOfTimes) + aCount
else
-- Otherwise add a new record to the list of records and the value itself to the checklist.
set end of o's listOfRecords to {aName:aValue, numberOfTimes:aCount}
set end of o's checklist to aValue
set checklistLength to checklistLength + 1
end if
end repeat
-- Derive a mutable array of dictionaries from the list of records just built.
set anArray to |⌘|'s class "NSMutableArray"'s arrayWithArray:(o's listOfRecords)
-- Get the highest "numberOfTimes" value contained in any of the dictionaries.
set highestFrequency to anArray's valueForKeyPath:("@max.numberOfTimes")
-- Filter for the dictionaries having that "numberOfTimes" value.
set aPredicate to |⌘|'s class "NSPredicate"'s predicateWithFormat_("numberOfTimes == %@", highestFrequency)
tell anArray to filterUsingPredicate:(aPredicate)
-- Get the "aName" values from these dictionaries.
set mostFrequentValues to anArray's valueForKey:("aName")
-- Return these and the "numberOfTimes" value.
return {values:mostFrequentValues as list, numberOfTimes:highestFrequency as integer}
end mostProlificItems
Edit: Speeded up slightly and shortened by having the case-insensitive section iterate through an AppleScript list instead of through the ordered set and by using this section instead of a separate, purely ASObjC one for case-sensitive work as well!