If you have an NSArray of strings
{ @\"ONE\", @\"ONE\", @\"ONE\", \"TWO\", @\"THREE\", @\"THREE\" }
How would I turn that into
<
Here's a nice category that defines a custom operator like @distinctUnionOfObjects, except it only works on strings and it will maintain their original order. Note: It does not sort the strings for you. It leaves intact only the first instance of whatever strings are repeated.
Usage:
#import "NSArray+orderedDistinctUnionOfStrings.h"
...
// if you feed it an array that has already been ordered, it will work as expected
NSArray *myArray = @[@"ONE", @"ONE", @"ONE", @"TWO", @"THREE", @"THREE"];
NSArray *myUniqueArray = [myArray valueForKeyPath:@"@orderedDistinctUnionOfStrings.self"];
Output:
myUniqueArray = ( "ONE", "TWO", "THREE" )
.h file:
#import
@interface NSArray (orderedDistinctUnionOfStrings)
@end
.m file:
#import "NSArray+orderedDistinctUnionOfObjects.h"
@implementation NSArray (orderedDistinctUnionOfObjects)
- (id) _orderedDistinctUnionOfStringsForKeyPath:(NSString*)keyPath {
NSMutableIndexSet *removeIndexes = [NSMutableIndexSet indexSet];
for (NSUInteger i = 0, n = self.count; i < n; ++i) {
if ([removeIndexes containsIndex:i]) {
continue;
}
NSString *str1 = [[self objectAtIndex:i] valueForKeyPath:keyPath];
for (NSUInteger j = i+1; j < n; ++j) {
if ([removeIndexes containsIndex:j]) {
continue;
}
id obj = [self objectAtIndex:j];
NSString *str2 = [obj valueForKeyPath:keyPath];
if ([str1 isEqualToString:str2]) {
[removeIndexes addIndex:j];
}
}
}
NSMutableArray *myMutableCopy = [self mutableCopy];
[myMutableCopy removeObjectsAtIndexes:removeIndexes];
return [[NSArray arrayWithArray:myMutableCopy] valueForKeyPath:[NSString stringWithFormat:@"@unionOfObjects.%@", keyPath]];
}
@end
And here is an excellent read on how to generate your own operators, and demystifies (by a little bit) how this works: http://bou.io/KVCCustomOperators.html