2012-05-06 3 views
29

Ich habe zwei NSArrays:subtrahieren Objekte in einer NSArray aus einem anderen Array

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

Und ich möchte, dass sie XOR. So etwas wie wants - needs so dass das, was ich habe links ist

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

ich normalerweise durch einige schwere Looping gehen würde, aber ich bin sicher, es ist ein praktischer Weg. Was soll ich stattdessen tun?

Antwort

58

So ähnlich?

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

Wont dieser Absturz, wenn Bedürfnisse enthält Objekte, die nicht vorhanden sind in will? – TompaLompa

+3

@TompaLompa Nein, es stürzt nicht ab. Aus den NSMutableArray-Dokumenten: 'Wenn das empfangende Array keine Objekte in otherArray enthält, hat die Methode keine Auswirkungen (obwohl sie den Aufwand für die Suche nach Inhalten verursacht)." – highlycaffeinated

+0

Dies ist KEIN XOR, als ob die Notwendigkeit ein Objekt enthält will nicht, das Ergebnis wird dieses Objekt nicht enthalten. –

8

Kirby Antwort ist in Ordnung, aber: Wenn Sie nicht über die Reihenfolge der Elemente in der Arrays ist es egal, sollten Sie stattdessen unter Verwendung von Sätzen werden. Wenn die Reihenfolge wichtig ist, könnten Sie NSOrderedSet in Betracht ziehen. Sie können die -minusSet: oder, für die letztere, -minusOrderedSet: Methoden verwenden.

+0

Dies ist definitiv der Weg zu gehen. Ich stelle mir vor, dass die Reihenfolge in diesem Beispiel nicht wichtig ist, aber selbst wenn dies der Fall ist, sind die Sets für dieses Verhalten sehr optimiert. –

+1

Beachten Sie, dass 'NSOrderedSet' nur in OSX ≥ 10.7 und iOS ≥ 5.0 verfügbar ist. –

0

Try This:

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

Ich habe nicht downvote, aber dieser Algorithmus ist mindestens O (n^2), wenn es viel einfacher sein sollte. – dreamlax

+1

Ja, wahrscheinlich nicht der beste Weg. – jpswain

2

Gegeben zwei Annahmen: dass die Reihenfolge keine Rolle spielt (oder wiederhergestellt werden kann - zB wenn die Arrays nun sortiert sind) * und dass kein Element erscheint mehr als einmal in entweder Array (obwohl Sie einen gezählten Satz dafür verwenden können), könnte ein Satz eine gute Wahl sein.

Die XOR (streng, die symmetrische Differenz) ist von zwei Sätzen die Vereinigung abzüglich der Schnitt:

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

[unioned minusSet:intersection]; 

* Wenn Auftrag wichtig ist, können Sie NSOrderedSet verwenden.

7

Wie wäre es mit Prädikaten?

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