【问题标题】:Subtract objects in one NSArray from another array从另一个数组中减去一个 NSArray 中的对象
【发布时间】:2012-05-15 09:51:19
【问题描述】:

我有两个 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];

我通常会经历一些繁重的循环,但我相信还有更实用的方法。我应该怎么做?

【问题讨论】:

    标签: objective-c cocoa cocoa-touch nsarray subtraction


    【解决方案1】:

    这样的?

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

    【讨论】:

    • 如果需要包含需要中不存在的对象,那不会崩溃吗?
    • @TompaLompa 不,它不会崩溃。来自 NSMutableArray 文档:If the receiving array does not contain objects in otherArray, the method has no effect (although it does incur the overhead of searching the contents).
    • 这不是异或,好像需要包含一个不想要的对象,结果将不包含该对象。
    • 幸运的是,这双鞋也很合脚,这是一个非常简单/巧妙的解决方案。我知道必须有比我打算做的更短的方法..
    【解决方案2】:

    使用谓词怎么样?

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

    【讨论】:

    • 嗨@Gyfis,使用谓词可以减少过滤数据的一半时间。感谢您提供此解决方案。
    【解决方案3】:

    Kirby 的回答很好,但是:如果您不关心数组中元素的顺序,则应该改用集合。如果顺序很重要,可以考虑NSOrderedSet。您可以使用 -minusSet: 或对于后者,-minusOrderedSet: 方法。

    【讨论】:

    • 这绝对是要走的路。我想在这个例子中顺序并不重要,但即使是这样,集合也针对这种行为进行了高度优化。
    • 请注意,NSOrderedSet 仅适用于 OSX ≥ 10.7 和 iOS ≥ 5.0。
    【解决方案4】:

    假设有两个假设:顺序不重要(或可以恢复 - 例如,如果数组现在已排序)* 并且没有项目在任一数组中出现多次(尽管您可以为此使用计数集),一个集合可能是一个不错的选择。

    两个集合的 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

    【讨论】:

      【解决方案5】:

      试试这个:

      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];
      }
      

      【讨论】:

      • 我没有投反对票,但这个算法至少是 O(n^2),而它应该更简单。
      • 是的,可能不是最好的方法。
      猜你喜欢
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-06
      • 2017-01-28
      相关资源
      最近更新 更多