【问题标题】:Compare objects in two Collections比较两个集合中的对象
【发布时间】:2014-12-06 23:08:42
【问题描述】:

我有以下场景:

我有两个集合类(可以是 NSArrayNSMutableArrayNSSetNSOrderedSet 或任何最适合这种情况的对象),它们包含相同类型的唯一对象(在某种意义上是唯一的对于集合中没有两个元素的所有对象,isEqual 方法将返回 true)。

假设第一个集合实例包含以下对象 (1,2,3,4,5) 和第二个 (2,3,4,6,7)。现在我需要一个方法来返回两个集合之间的差异,以及每个集合之间的差异究竟是什么的额外信息。 该示例的示例结果为:(1,5) was removed from the first collection and (6,7) added two the second collection

我知道如果我将NSMutableArray 与排序列表一起使用并确定哪个列表的元素比另一个列表多,我可以使用removeObjectsInArray 来获取不同对象的列表(如Compare two arrays with the same value but with a different orderHow to compare and remove common objects( NSDictionaries) from 2 NSMutableArray?),但不知道哪些对象在哪个集合中。我可以创建一个临时集合并将removeObjectsInArray 的结果放入该数组中,并将另外两个初始数组与临时数组进行比较。不过似乎有点冗长。有没有更好的方法我不知道?

【问题讨论】:

  • 顺序重要吗?也就是说,如果第二个数组是4,3,2,7,6,答案会不会不一样?
  • 不,顺序无关紧要。

标签: ios objective-c arrays collections


【解决方案1】:

我找到了一种使用 NSPredicate 来做你想做的事的更巧妙的方法。当我运行以下代码时:

NSArray *firstArray = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",@"7", nil];
NSArray *secondArray = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"8",nil];

NSArray *itemsMissingFromSecondArray = [firstArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT SELF IN %@", secondArray]];
NSArray *itemsMissingFromFirstArray = [secondArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT SELF IN %@", firstArray]];

NSLog(@"itemsMissingFromFirstArray=%@\nitemsMissingFromSecondArray=%@", itemsMissingFromFirstArray, itemsMissingFromSecondArray);

我得到以下输出,显示了另一个数组中每个数组中缺少的内容:

itemsMissingFromFirstArray=(
    8
)
itemsMissingFromSecondArray=(
    4,
    5,
    6,
    7
)

比排序合并代码少,不使用一堆临时数组,简单易读。

注意:如果有人还想知道两个数组中的项目,解决方案同样简单:

NSArray *itemsFoundInBothArrays = [firstArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF IN %@", secondArray]];

【讨论】:

  • 事实上我很喜欢这个解决方案!它具有函数式编程的味道,让我想起了 Haskell。不错!
【解决方案2】:

我想如果你想知道区别,你可以使用 NSMutableSet 和 minusSet 函数。

 [set1 minusSet:set2];

将立即为您提供 set1 中的元素,但不会立即提供 set2 中的元素。所以你不需要任何临时集合并再次与原始集合进行比较。

否则,如果你只想删除元素,你可以使用 NSArray 并这样做:

 [secondArray removeObjectsInArray:firstArray];

编辑: 一次性找出所有差异:

 [ [set1 unionSet:set2] minusSet: [set1 intersectSet:set2] ];

【讨论】:

  • minusSet 的问题与removeObjectsInArray 相同,您只能从一组/数组中获得差异,而不是从两者中获得差异。 minusSet 基本上是 removeObjectsInArrayset 集合。
  • 编辑了答案。我认为您可以像这样在一行中做到这一点。
  • 我非常感谢您尝试提供帮助,但您的回答在很多方面都是错误的。例如unionSetintersectSet 都是void 函数,因此使用minusSet 将不会发生事件。我可以看到你想要做什么,但是我需要几个临时集合,即使这样我也只能得到两个差异的并集,仍然不知道哪个集合缺少哪个对象。
【解决方案3】:
+ (NSArray *) removeObjectsFromArray :(NSArray *)arrayToRemoveFrom thatAreAlsoIn:(NSArray *)arrayOfItemsToRemove
{
    NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:arrayToRemoveFrom];
    [newArray removeObjectsInArray:arrayOfItemsToRemove];    
    return newArray;
}

+(void) findArrayDifferences
{
    NSArray *bigArray = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",@"7", nil];
    NSArray *smallArray = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"8",nil];

    NSArray *itemsInBigArrayThatAreNotInSmallArray = [self removeObjectsFromArray:bigArray thatAreAlsoIn:smallArray];

    NSArray *itemsThatAreInBothArrays = [self removeObjectsFromArray:bigArray thatAreAlsoIn:itemsInBigArrayThatAreNotInSmallArray];

    NSArray *itemsInSmallArrayThatAreNotInBigArray = [self removeObjectsFromArray:smallArray thatAreAlsoIn:itemsThatAreInBothArrays];

    NSLog(@"itemsInBigArrayThatAreNotInSmallArray=%@\nitemsThatAreInBothArrays=%@\nitemsInSmallArrayThatAreNotInBigArray=%@", itemsInBigArrayThatAreNotInSmallArray, itemsThatAreInBothArrays, itemsInSmallArrayThatAreNotInBigArray);
}

这会产生以下输出:

itemsInBigArrayThatAreNotInSmallArray=(
    4,
    5,
    6,
    7
)
itemsThatAreInBothArrays=(
    1,
    2,
    3
)
itemsInSmallArrayThatAreNotInBigArray=(
    8
)

【讨论】:

  • removeObjectsInArray 是一个void 函数。
  • 抱歉,回答匆忙。尽管我意识到您可能不想使用临时数组,但我将其更新为一个工作示例。
  • 查看我的其他答案,了解我认为您会喜欢的更巧妙的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
  • 2020-04-17
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多