2012-05-06 9 views
29

que tienen dos NSArrays:objetos Restar en uno NSArray de otra matriz

NSArray *wants = [NSArray arrayWithObjects: 
        @"apples", 
        @"oranges", 
        @"pineapple", 
        @"mango", 
        @"strawberries", 
        nil]; 
NSArray *needs = [NSArray arrayWithObjects: 
        @"apples", 
        @"pineapple", 
        @"strawberries", 
        nil]; 

Y quiero XOR ellos. Algo así como wants - needs de modo que lo que me queda es

[NSArray arrayWithObjects: 
@"oranges", 
@"mango", 
nil]; 

normalmente me gustaría ir a través de algunos bucles pesado, pero estoy seguro de que hay una manera más práctica. ¿Qué debería hacer?

Respuesta

58

¿Algo como esto?

NSMutableArray *array = [NSMutableArray arrayWithArray:wants]; 
[array removeObjectsInArray:needs]; 
+1

¿No cuelga si las necesidades contienen objetos que no existen en los deseos? – TompaLompa

+3

@TompaLompa No, no falla. Desde los documentos NSMutableArray: 'Si la matriz receptora no contiene objetos en otroArray, el método no tiene efecto (aunque incurre en la sobrecarga de la búsqueda de los contenidos) .' – highlycaffeinated

+0

Esto NO es un XOR, como si las necesidades contienen un objeto que quiere no, el resultado no contendrá ese objeto. –

8

respuesta de Kirby está bien, pero: si no se preocupan por el orden de los elementos en las matrices, usted debe utilizar conjuntos en su lugar. Si el pedido es importante, puede considerar NSOrderedSet. Puede usar el -minusSet: o, para este último, los métodos -minusOrderedSet:.

+0

Este es definitivamente el camino a seguir. Me imagino que el orden no es importante en este ejemplo, pero incluso si lo es, los conjuntos están altamente optimizados para este tipo de comportamiento. –

+1

Tenga en cuenta que 'NSOrderedSet' solo está disponible en OSX ≥ 10.7 y iOS ≥ 5.0. –

0

intenta esto:

NSArray *NSArray_XOR(NSArray *arr1, NSArray *arr2) 
{ 
    NSMutableArray *results = [NSMutableArray array]; 

    for (int i = 0; i < arr1.count; i++) { 
     id obj = [arr1 objectAtIndex:i]; 

     if (![arr2 containsObject:obj]) 
      [results addObject:obj]; 
    } 

    for (int i = 0; i < arr2.count; i++) { 
     id obj = [arr2 objectAtIndex:i]; 

     if (![arr1 containsObject:obj]) 
      [results addObject:obj]; 
    } 

    // make a unmutable copy of the array. 
    return [NSArray arrayWithArray:results]; 
} 
+3

No he votado negativamente, pero este algoritmo es al menos O (n^2) cuando debería ser mucho más simple. – dreamlax

+1

Sí, probablemente no sea la mejor manera. – jpswain

2

Dados dos supuestos: que el orden no es importante (o puede ser restaurado - por ejemplo, si los arreglos se clasifican ahora) * y que ningún elemento aparece más de una vez en cualquiera array (aunque puede usar un conjunto contado para esto), un conjunto podría ser una buena opción.

El XOR (en sentido estricto, la diferencia simétrica) de dos conjuntos es la unión menos la intersección:

NSMutableSet * unioned = [NSMutableSet setWithArray:wants]; 
[unioned unionSet:[NSSet setWithArray:needs]]; 
NSMutableSet * intersection = [NSMutableSet setWithArray:needs]; 
[intersection intersectSet:[NSSet setWithArray:wants]]; 

[unioned minusSet:intersection]; 

* Si el orden es importante, puede utilizar NSOrderedSet.

7

¿Qué le parece usar los predicados?

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", needs]; 
NSArray *wants_needs = [wants filteredArrayUsingPredicate:predicate]; 
Cuestiones relacionadas