iphone - ¿Cómo convertir un NSArray de cadenas en un conjunto de cadenas únicas, en el mismo orden?
objective-c ios (5)
Aquí hay una buena categoría que define un operador personalizado como @distinctUnionOfObjects
, excepto que solo funciona en cadenas y mantendrá su orden original . Nota: No ordena las cuerdas por ti. Deja intacto solo la primera instancia de cualquier secuencia que se repite.
Uso:
#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"];
Salida:
myUniqueArray = ( "ONE", "TWO", "THREE" )
archivo .h:
#import <Foundation/Foundation.h>
@interface NSArray (orderedDistinctUnionOfStrings)
@end
archivo .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
Y aquí hay una excelente lectura sobre cómo generar sus propios operadores, y desmitifica (un poco) cómo funciona esto: http://bou.io/KVCCustomOperators.html
Si tienes una NSArray de cadenas
{ @"ONE", @"ONE", @"ONE", "TWO", @"THREE", @"THREE" }
¿Cómo podría convertir eso en
{ @"ONE", @"TWO", @"THREE" }
..donde la matriz sigue el mismo orden que el original. Creo que puede convertir una matriz en un NSSet para obtener elementos únicos, pero si la vuelve a convertir en una matriz, no tiene la garantía de obtener el mismo pedido.
Creo que puedes hacer esto con eso
NSArray * uniqueArray = [[Yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
espero que esto te ayude
Hmm ... ¿podrías usar un bucle?
NSMutableArray *newarray = [[NSMutableArray alloc] init];
NSString *laststring = nil;
for (NSString *currentstring in oldarray)
{
if (![currentstring isEqualtoString:laststring]) [newarray addObject:currentstring];
laststring = currentstring
}
Mi primer pensamiento fue que podías hacer:
NSArray * a = [NSArray arrayWithObjects:@"ONE", @"ONE", @"ONE", @"TWO", @"THREE", @"THREE", nil];
NSLog(@"%@", [a valueForKeyPath:@"@distinctUnionOfObjects.self"]);
Pero eso no mantiene el orden. Por lo tanto, tienes que hacerlo 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];
}
}
Utilizo un NSMutableSet
para determinar si ya me he encontrado con esta entrada antes (a diferencia de [unique containsObject:string]
NSMutableSet
de NSMutableSet
de NSMutableSet
[unique containsObject:string]
, ya que un conjunto tendrá un tiempo de búsqueda O (1) y una matriz tiene un tiempo de búsqueda O (n). Si solo está tratando con un pequeño número de objetos, entonces esto no importará. Sin embargo, si la matriz de origen es muy grande, entonces usar el conjunto para determinar la singularidad puede agregar un poco de aumento de velocidad. debería usar Instrumentos para perfilar su código y ver si es necesario)
Podrías hacer esto:
NSArray * uniqueArray = [[NSOrderedSet orderedSetWithArray:duplicatesArray] array];
De esta manera, también conservas el orden!