文字列のNSArrayがある場合
{ @"ONE", @"ONE", @"ONE", "TWO", @"THREE", @"THREE" }
どうすればそれを
{ @"ONE", @"TWO", @"THREE" }
..配列が元の配列と同じ順序に従う場合。配列をNSSetに変換して一意のアイテムを取得できると思いますが、配列に戻すと、同じ順序を取得できるとは限りません。
私の最初の考えはあなたができるということでした:
NSArray * a = [NSArray arrayWithObjects:@"ONE", @"ONE", @"ONE", @"TWO", @"THREE", @"THREE", nil];
NSLog(@"%@", [a valueForKeyPath:@"@distinctUnionOfObjects.self"]);
しかし、それは秩序を維持しません。したがって、手動で行う必要があります。
NSArray * a = [NSArray arrayWithObjects:@"ONE", @"ONE", @"ONE", @"TWO", @"THREE", @"THREE", nil];
NSMutableArray * unique = [NSMutableArray array];
NSMutableSet * processed = [NSMutableSet set];
for (NSString * string in a) {
if ([processed containsObject:string] == NO) {
[unique addObject:string];
[processed addObject:string];
}
}
NSMutableSet
を使用して、以前にこのエントリに遭遇したことがあるかどうかを判断します([unique containsObject:string]
とは対照的に、セットにはO(1)ルックアップがあるため)時間、および配列にはO(n)ルックアップ時間があります。少数のオブジェクトのみを処理している場合、これは問題ではありません。ただし、ソース配列が非常に大きい場合は、セットを使用して一意性を判断すると、速度が少し向上する可能性があります(ただし、Instrumentsを使用してコードのプロファイルを作成し、必要かどうかを確認する必要があります)
あなたはこのようにすることができます:
NSArray * uniqueArray = [[NSOrderedSet orderedSetWithArray:duplicatesArray] array];
このようにして、順序も保持します!
私はあなたがそれでこれを行うことができると思います
NSArray * uniqueArray = [[Yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
これがお役に立てば幸いです
これは、@distinctUnionOfObjects
のような カスタム演算子 を定義するNiceカテゴリです。ただし、文字列でのみ機能し、元の順序を維持します。注:文字列はソートされません。繰り返される文字列の最初のインスタンスのみがそのまま残ります。
使用法:
#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"];
出力:
myUniqueArray = ( "ONE", "TWO", "THREE" )
.hファイル:
#import <Foundation/Foundation.h>
@interface NSArray (orderedDistinctUnionOfStrings)
@end
.mファイル:
#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
そして、これはあなた自身の演算子を生成する方法についての優れた読み物であり、これがどのように機能するかを(少しだけ)わかりやすく説明しています: http://bou.io/KVCCustomOperators.html
うーん..あなたはただループを使うことができますか?
NSMutableArray *newarray = [[NSMutableArray alloc] init];
NSString *laststring = nil;
for (NSString *currentstring in oldarray)
{
if (![currentstring isEqualtoString:laststring]) [newarray addObject:currentstring];
laststring = currentstring
}