2012-05-06 42 views
29

Tôi có hai NSArrays:đối tượng Subtract trong một NSArray từ một mảng

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

Và tôi muốn XOR họ. Một cái gì đó như wants - needs để những gì tôi đã để lại là

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

Tôi thường sẽ đi qua một số vòng lặp nặng, nhưng tôi chắc chắn có một cách thực tế hơn. Tôi nên làm gì?

Trả lời

58

Một cái gì đó như thế này?

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

Sẽ không xảy ra sự cố nếu nhu cầu chứa các đối tượng không tồn tại khi muốn? – TompaLompa

+3

@TompaLompa Không, nó không sụp đổ. Từ các tài liệu NSMutableArray: 'Nếu mảng nhận không chứa các đối tượng trong mảng khác, phương thức này không có hiệu lực (mặc dù nó phải chịu chi phí tìm kiếm nội dung). ' – highlycaffeinated

+0

Đây không phải là một XOR, như thể các nhu cầu có chứa một đối tượng không muốn, kết quả sẽ không chứa đối tượng đó. –

8

Câu trả lời của Kirby là tốt, nhưng: nếu bạn không quan tâm đến thứ tự của các phần tử trong mảng, bạn nên sử dụng bộ thay thế. Nếu đơn đặt hàng quan trọng, bạn có thể xem xét NSOrderedSet. Bạn có thể sử dụng -minusSet: hoặc đối với phương thức sau, -minusOrderedSet:.

+0

Điều này chắc chắn là con đường để đi. Tôi đang tưởng tượng thứ tự không quan trọng trong ví dụ này, nhưng ngay cả khi nó là, bộ được tối ưu hóa cao cho loại hành vi này. –

+1

Lưu ý rằng 'NSOrderedSet' chỉ khả dụng trong OSX ≥ 10.7 và iOS ≥ 5.0. –

0

Hãy thử này:

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

Tôi đã không downvote, nhưng thuật toán này là ít nhất O (n^2) khi nó nên đơn giản hơn nhiều. – dreamlax

+1

Có thể không phải là cách tốt nhất. – jpswain

2

Với hai giả định: rằng thứ tự là không quan trọng (hoặc có thể được phục hồi - ví dụ, nếu các mảng đều được sắp xếp bây giờ) * và không có mục xuất hiện nhiều hơn một lần trong cả hai mảng (mặc dù bạn có thể sử dụng một bộ đếm cho điều này), một tập hợp có thể là một lựa chọn tốt.

Các XOR (Nghiêm, sự khác biệt đối xứng) của hai bộ là sự kết hợp trừ đi giao lộ:

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

[unioned minusSet:intersection]; 

* Nếu trật tự là rất quan trọng, bạn có thể sử dụng NSOrderedSet.

7

Làm thế nào về việc sử dụng vị từ?

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", needs]; 
NSArray *wants_needs = [wants filteredArrayUsingPredicate:predicate]; 
Các vấn đề liên quan