This is a script object that encompasses a Cocoa array, for use from Mavericks scripts via an ASObjC-based library. It is similar to the one for sets. See macscripter.net/viewtopic.php?id=41638 for how to set up and use a script library.
use framework "Foundation"
script BaseObject -- the parent script object, required for AppleScriptObjC inheritance
end script
on smartListWith:aList -- call to make a new smartList
script SmartList
property parent : BaseObject -- for inheritance
property arrayStore : missing value -- where the array is stored
on countOfArray() -- get count of items
return arrayStore's |count|() as integer
end countOfArray
-- get objects and indexes
on objectAtIndex:anInteger
set anInteger to my correctIndex:anInteger
set theResult to arrayStore's objectAtIndex:anInteger
return my coerceToASClass:theResult
end objectAtIndex:
on objectsFrom:anInteger toIndex:endInteger -- get range of objects
set anInteger to my correctIndex:anInteger
set endInteger to my correctIndex:endInteger
return (arrayStore's subarrayWithRange:(current application's NSMakeRange(anInteger, endInteger - anInteger + 1))) as list
end objectsFrom:toIndex:
on indexOfObject:anObject
try -- will error if not found because NSNotFound is too big to coerce to an integer
set theResult to ((arrayStore's indexOfObject:anObject) as integer) + 1
on error
return 0
end try
return theResult
end indexOfObject:
-- add objects
on addObject:anObject -- adds to end
arrayStore's addObject:anObject
end addObject:
on addObjectsFromArray:anObject -- adds to end
arrayStore's addObjectsFromArray:anObject
end addObjectsFromArray:
on insertObject:anObject atIndex:anInteger
set anInteger to my correctIndex:anInteger
arrayStore's insertObject:anObject atIndex:anInteger
end insertObject:atIndex:
-- remove objects
on removeObject:anObject
arrayStore's removeObject:anObject
end removeObject:
on removeObjects:newList
arrayStore's removeObjectsInArray:newList
end removeObjects:
on removeObjectAtIndex:anInteger
set anInteger to my correctIndex:anInteger
arrayStore's removeObjectAtIndex:anInteger
end removeObjectAtIndex:
on removeObjectsFrom:anInteger toIndex:endInteger
set anInteger to my correctIndex:anInteger
set endInteger to my correctIndex:endInteger
arrayStore's removeObjectsInRange:(current application's NSMakeRange(anInteger, endInteger - anInteger))
end removeObjectsFrom:toIndex:
-- replace objects
on replaceObjectAtIndex:anInteger withObject:anObject
set anInteger to my correctIndex:anInteger
arrayStore's replaceObjectAtIndex:anInteger withObject:anObject
end replaceObjectAtIndex:withObject:
-- swap objects
on swapObjectAtIndex:anInteger withObjectAtIndex:endInteger
set anInteger to my correctIndex:anInteger
set endInteger to my correctIndex:endInteger
arrayStore's exchangeObjectAtIndex:anInteger withObjectAtIndex:endInteger
end swapObjectAtIndex:withObjectAtIndex:
-- sort objects
on sortIgnoringCase()
my sortUsingSelector:"localizedCaseInsensitiveCompare:"
end sortIgnoringCase
on sortConsideringCase()
my sortUsingSelector:"localizedCompare:"
end sortConsideringCase
on sortLikeFinder()
my sortUsingSelector:"localizedStandardCompare:"
end sortLikeFinder
on standardSort() -- use for other than strings
my sortUsingSelector:"compare:"
end standardSort
-- misc functions
on containsObject:anObject -- whether array contains an object
return ((arrayStore's containsObject:anObject) as integer = 1)
end containsObject:
on firstObjectCommonWithArray:newArray
set theResult to arrayStore's firstObjectCommonWithArray:newArray
return my coerceToASClass:theResult
end firstObjectCommonWithArray:
on componentsJoinedByString:aString
return (arrayStore's componentsJoinedByString:aString) as text
end componentsJoinedByString:
on pathsMatchingExtensions:aList -- no "." in extensions
return (arrayStore's pathsMatchingExtensions:aList) as list
end pathsMatchingExtensions:
on valueForKey:aString -- calls valueForKey: on every item in array
return (arrayStore's valueForKey:aString) as list
end valueForKey:
on valueForKeyPath:aString -- calls valueForKey: on every item in array, one key after the other (keys separated by ".")
return (arrayStore's valueForKeyPath:aString) as list
end valueForKeyPath:
on sumAndAverage() -- return {sum, average} if list is numbers
return {(arrayStore's valueForKeyPath:"@sum.self") as real, (arrayStore's valueForKeyPath:"@avg.self") as real}
end sumAndAverage
on maxAndMin() -- return {max, min}
return {(arrayStore's valueForKeyPath:"@max.self") as real, (arrayStore's valueForKeyPath:"@min.self") as real}
end maxAndMin
on setValue:aValue forKey:aString
arrayStore's setValue:aValue forKey:aString
end setValue:forKey:
-- filtering; requires valid predicate string
on filteredArrayUsingPredicateString:aString -- return filtered list
set thePredicate to current application's NSPredicate's predicateWithFormat:aString
return (arrayStore's filteredArrayUsingPredicate:thePredicate) as list
end filteredArrayUsingPredicateString:
on filterUsingPredicateString:aString -- filter in place
set thePredicate to current application's NSPredicate's predicateWithFormat:aString
arrayStore's filterUsingPredicate:thePredicate
end filterUsingPredicateString:
-- return as list/array
on asArray()
return arrayStore
end asArray
on asList()
return arrayStore as list
end asList
-- handlers for script's use
on correctIndex:anInteger -- for script's use; convert AS index to Cocoa index
if anInteger < 0 then
return anInteger + (my countOfSet())
else
return anInteger - 1
end if
end correctIndex:
on coerceToASClass:anObject -- for script's use; coerce to AS class for return
if ((anObject's isKindOfClass:(current application's NSArray)) as integer = 1) then
return anObject as list
else -- coerce to list and return item 1; workaround to coerce item of unknown class
set anObject to anObject as list
return item 1 of anObject
end if
end coerceToASClass:
on sortUsingSelector:theSel -- for script's use
set theDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"self" ascending:true selector:theSel
arrayStore's sortUsingDescriptors:{theDesc}
end sortUsingSelector:
end script
set arrayStore of SmartList to current application's NSMutableArray's arrayWithArray:aList
return SmartList
end smartListWith:
Some example code:
use theLib : script "<name of library>"
use scripting additions
set theList to theLib's smartListWith:{1, 2, 3, 5, 3, 2, 6}
log (theList's indexOfObject:5)
theList's insertObject:"blah" atIndex:3
log theList's asList()
log (theList's firstObjectCommonWithArray:{4, 5, 3})
theList's removeObjectAtIndex:3
log theList's asList()
log (theList's filteredArrayUsingPredicateString:"SELF > 2")
log (theList's componentsJoinedByString:" and ")
log (theList's valueForKey:"doubleValue")
(theList's valueForKey:"stringValue")
Edited to add handlers valueForKeyPath:, sumAndAverage(), and maxAndMin().