I’ve been working on a project, and a good night’s sleep didn’t suggest a solution. Although not shown, a lexical sort will be done to both of the arrays at the top of the script.
use framework "Foundation"
set listOne to {"line 1", "line 2", "line 3", "line 4", "line 5", "line 5"}
set listTwo to {"line 1", "line 2", "line 5", "line 6", "line 7"}
set arrayOne to current application's NSArray's arrayWithArray:listOne
set arrayTwo to current application's NSArray's arrayWithArray:listTwo
# desired return values
# arrayOneUnique --> {"line 3", "line 4", "line 5"}
# arrayTwoUnique --> {"line 6", "line 7"}
# commonBothArrays --> {"line 1", "line 2", "line 5"}
Nigel. Thanks for looking at my post. I had considered using sets but didn’t pursue that because the arrays will occasionally/often have duplicate items. Perhaps I should reconsider that because of set’s comparing sets methods.
use framework "Foundation"
set listOne to {"line 1", "line 2", "line 3", "line 4", "line 5", "line 5"}
set listTwo to {"line 1", "line 2", "line 5", "line 6", "line 7"}
set arrayOne to current application's NSArray's arrayWithArray:listOne
set arrayTwo to current application's NSArray's arrayWithArray:listTwo
set arrayOneUnique to current application's NSMutableArray's new()
set arrayTwoUnique to arrayTwo's mutableCopy()
set commonArray to current application's NSMutableArray's new()
repeat with anItem in arrayOne
if (arrayTwoUnique's containsObject:anItem) is true then --item in both arrays
(commonArray's addObject:anItem)
(arrayTwoUnique's removeObject:anItem)
else --item in arrayOne only
(arrayOneUnique's addObject:anItem)
end if
end repeat
arrayOneUnique as list --> {"line 3", "line 4", "line 5"}
arrayTwoUnique as list --> {"line 6", "line 7"}
commonArray as list --> {"line 1", "line 2", "line 5"}
I think peavine’s nailed it. But just for interest using NSCountedSet methods:
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
set listOne to {"line 1", "line 2", "line 3", "line 4", "line 5", "line 5"}
set listTwo to {"line 1", "line 2", "line 5", "line 6", "line 7"}
set setOneUnique to current application's NSCountedSet's alloc()'s initWithArray:(listOne)
set setTwoUnique to current application's NSCountedSet's alloc()'s initWithArray:(listTwo)
set commonSet to setOneUnique's |copy|() -- |copy|() or mutableCopy() doesn't matter. It's an exclusively mutable class.
commonSet's intersectSet:(setTwoUnique)
setOneUnique's minusSet:(commonSet)
setTwoUnique's minusSet:(commonSet)
set sortDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:("self") ascending:(true)
set listOneUnique to unpackAndSort(setOneUnique, sortDescriptor) --> {"line 3", "line 4", "line 5"}
set listTwoUnique to unpackAndSort(setTwoUnique, sortDescriptor) --> {"line 6", "line 7"}
set commonList to unpackAndSort(commonSet, sortDescriptor) --> {"line 1", "line 2", "line 5"}
on unpackAndSort(countedSet, sortDescriptor)
-- sortedArrayUsingDescriptors: is inherited from NSSet via NSMutableSet.
set array to (countedSet's sortedArrayUsingDescriptors:({sortDescriptor}))'s mutableCopy()
-- Insert any duplicate values.
repeat with i from ((count array) - 1) to 0 by -1
set this to (array's objectAtIndex:(i))
repeat ((countedSet's countForObject:(this)) - 1) times
(array's insertObject:(this) atIndex:(i))
end repeat
end repeat
return array as list
end unpackAndSort
After further testing, my solution doesn’t work, because the removeObject method removes every instance of an object from arrayTwoUnique. However, the following appears to fix this issue:
use framework "Foundation"
set listOne to {"line 1", "line 2", "line 3", "line 4", "line 5", "line 5"}
set listTwo to {"line 1", "line 2", "line 5", "line 5", "line 6", "line 7"}
set arrayOne to current application's NSArray's arrayWithArray:listOne
set arrayTwo to current application's NSArray's arrayWithArray:listTwo
set arrayOneUnique to current application's NSMutableArray's new()
set arrayTwoUnique to arrayTwo's mutableCopy()
set commonArray to current application's NSMutableArray's new()
repeat with anItem in arrayOne
if (arrayTwoUnique's containsObject:anItem) is true then --item in both arrays
(commonArray's addObject:anItem)
set theIndex to (arrayTwoUnique's indexOfObject:anItem)
(arrayTwoUnique's removeObjectAtIndex:theIndex)
else --item in arrayOne only
(arrayOneUnique's addObject:anItem)
end if
end repeat
arrayOneUnique as list --> {"line 3", "line 4"}
arrayTwoUnique as list --> {"line 6", "line 7"}
commonArray as list --> {"line 1", "line 2", "line 5", "line 5"}
I tested Nigel’s suggestion with the above lists, and it worked great.