2つのNSArrayがあります。
NSArray *wants = [NSArray arrayWithObjects:
@"apples",
@"oranges",
@"pineapple",
@"mango",
@"strawberries",
nil];
NSArray *needs = [NSArray arrayWithObjects:
@"apples",
@"pineapple",
@"strawberries",
nil];
そして、私はそれらをXOR
したいと思います。何かのようなもの wants - needs
私が残したのは
[NSArray arrayWithObjects:
@"oranges",
@"mango",
nil];
私は通常、重いループを経験しますが、もっと実用的な方法があると確信しています。代わりに何をすべきですか?
このようなもの?
NSMutableArray *array = [NSMutableArray arrayWithArray:wants];
[array removeObjectsInArray:needs];
Kirbyの答えは問題ありませんが、配列内の要素の順序を気にしない場合は、代わりにセットを使用する必要があります。順序が重要な場合は、NSOrderedSet
を検討してください。 -minusSet:
を使用するか、後者の場合は-minusOrderedSet:
メソッドを使用できます。
述語を使うのはどうですか?
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", needs];
NSArray *wants_needs = [wants filteredArrayUsingPredicate:predicate];
2つの仮定が与えられます:順序が重要ではない(または復元できる-たとえば、配列が今ソートされている場合)*、およびどちらの配列にもアイテムが複数回表示されない(ただし、これにはカウントされたセットを使用できます)、セットは良い選択かもしれません。
2つのセットのXOR(厳密には対称差)は、和集合から共通部分を引いたものです。
NSMutableSet * unioned = [NSMutableSet setWithArray:wants];
[unioned unionSet:[NSSet setWithArray:needs]];
NSMutableSet * intersection = [NSMutableSet setWithArray:needs];
[intersection intersectSet:[NSSet setWithArray:wants]];
[unioned minusSet:intersection];
*順序が重要な場合は、 NSOrderedSet
を使用できます。
これを試して:
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];
}