Domanda

Se si dispone di un NSArray di stringhe

{ @"ONE", @"ONE", @"ONE", "TWO", @"THREE", @"THREE" }

Come faccio a trasformarla in

{ @"ONE", @"TWO", @"THREE" }

.. dove la matrice segue lo stesso ordine come l'originale. Penso che si può trasformare una matrice in un NSSet per ottenere oggetti unici, ma se lo si accende di nuovo in un array che non sono garantiti per ottenere lo stesso ordine ..

È stato utile?

Soluzione

Il mio pensiero iniziale era che si poteva fare:

NSArray * a = [NSArray arrayWithObjects:@"ONE", @"ONE", @"ONE", @"TWO", @"THREE", @"THREE", nil];
NSLog(@"%@", [a valueForKeyPath:@"@distinctUnionOfObjects.self"]);

Ma questo ordine non mantenere. Pertanto, è necessario farlo manualmente:

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];
  }
}

I utilizzare un NSMutableSet per determinare se ho già incontrato questa voce prima (al contrario di [unique containsObject:string], dal momento che una serie avrà O (1) ricerca di tempo, e un array ha O (n) tempo di ricerca. Se si 're solo a che fare con un piccolo numero di oggetti, allora questo non importa. Tuttavia, se la matrice di origine è molto grande, quindi utilizzando il set per determinare l'unicità può aggiungere un po' di un aumento di velocità. (tuttavia, è necessario utilizzare Gli strumenti al profilo il codice e vedere se è necessario)

Altri suggerimenti

Si potrebbe fare in questo modo:

NSArray * uniqueArray = [[NSOrderedSet orderedSetWithArray:duplicatesArray] array];

In questo modo, è anche preservare l'ordine!

Penso che si possa fare questo con che

NSArray * uniqueArray = [[Yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];

Spero che questo potrebbe aiutare a

Hmm .. si potrebbe utilizzare un ciclo?

NSMutableArray *newarray = [[NSMutableArray alloc] init];
NSString *laststring = nil;
for (NSString *currentstring in oldarray) 
{
   if (![currentstring isEqualtoString:laststring]) [newarray addObject:currentstring];
   laststring = currentstring
}

Ecco una bella categoria che definisce una personalizzato operatore come @distinctUnionOfObjects, tranne che funziona solo su stringhe e si manterranno la loro originale ordine. Nota: non ordina le stringhe per voi. Si lascia intatta solo la prima istanza di qualsiasi stringhe sono ripetuti.

Utilizzo:

#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" )

file h:

#import <Foundation/Foundation.h>

@interface NSArray (orderedDistinctUnionOfStrings)

@end

file .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

E qui è un eccellente lettura su come generare i propri operatori, e demistifica (da un po ') come funziona: http://bou.io/KVCCustomOperators.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top