查找两个NSMutableArrays的交集

40
我有三个NSMutableArray,包含根据不同的标准添加到列表中的名称。
以下是我的数组伪代码:
NSMutableArray *array1 = [@"Jack", @"John", @"Daniel", @"Lisa"];
NSMutableArray *array2 = [@"Jack", @"Bryan", @"Barney", @"Lisa",@"Penelope",@"Angelica"];
NSMutableArray *array3 = [@"Jack", @"Jerome", @"Dan", @"Lindsay", @"Lisa"];

我想要找到一个第四个数组,其中包含这三个数组的交集。例如,在这种情况下,它将是:

NSMutableArray *array4 = [@"Jack",@"Lisa"];

因为三个数组中都有Jack和Lisa作为元素。是否有简单的方法可以处理这种情况?

5个回答

74

使用 NSMutableSet

NSMutableSet *intersection = [NSMutableSet setWithArray:array1];
[intersection intersectSet:[NSSet setWithArray:array2]];
[intersection intersectSet:[NSSet setWithArray:array3]];

NSArray *array4 = [intersection allObjects];
这样做唯一的问题是你会失去元素的顺序,但我认为在这种情况下这是可以接受的。
正如评论中所指出的(感谢Q80!),iOS 5和OS X 10.7添加了一个名为NSOrderedSet的新类(带有一个Mutable子类),它允许您执行相同的交集操作,同时仍然保持顺序。

2
只要这些数组本身不包含重复的元素,这段代码就能正常工作(例如对于array1 = [obj1, obj2, obj2, obj3]array2 = [obj2, obj2, obj3, obj4],它们的交集应该是intersect = [obj2, obj2, obj3])。如果这些数组中包含重复的元素或者元素的顺序很重要,那么最好使用谓词来过滤这些数组。 - David Rönnqvist
1
@geekay_gk 它将使用方法 hashisEqual: 来确定哪些对象存在于两个集合中。 - David Rönnqvist
1
一个基类有一个只读方法返回布尔值,而子类有一个同名的void方法修改对象,这有点令人困惑。 - Eric Walker
3
如果您想保持顺序,请使用NSMutableOrderedSet。类似于:NSMutableOrderedSet *ordered = [NSMutableOrderedSet orderedSetWithArray:array1];,然后执行交集等操作。 - Q8i
1
示例代码不会产生预期结果,因为您正在将A与B相交,然后将该交集的结果与C相交;((A.intersect B).intersect C)。您想要做的是将每个数组与所有其他数组的并集相交;(A.intersect (B union C)) + (B.intersect (A union C)) + (C.intersect (B union C))。 - Voxar
显示剩余3条评论

2

这种方法比使用NSSet更加简洁,并且不会丢失原始顺序。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self IN %@ AND self IN %@", array2, array3];
NSArray *array4 = [array1 filteredArrayUsingPredicate:predicate];

2

请看这篇文章

简而言之:如果您可以使用NSSet而不是NSArray,则很容易(NSMutableSet具有intersectSet:)。

否则,您可以从NSArray构建一个NSSet并返回上述情况。


1
NSMutableArray *first = [[NSMutableArray alloc] initWithObjects:@"Jack", @"John", @"Daniel", @"Lisa",nil];

NSMutableArray *seconds =[[NSMutableArray alloc] initWithObjects:@"Jack", @"Bryan", @"Barney", @"Lisa",@"Penelope",@"Angelica",nil];

NSMutableArray *third = [ [ NSMutableArray alloc]init];


for (id obj in first) {

    if ([seconds  containsObject:obj] ) {


        [third addObject:obj];

    }


}


NSLog(@"third is : %@ \n\n",third);

输出:

第三个是:(

Jack,

Lisa

)


-1

这是上面链接中的一个可工作的变体

NSPredicate *intersectPredicate = [NSPredicate predicateWithFormat:@"SELF IN %@", @[@500, @400, @600]];
NSArray *intersect = [@[@200, @300, @400] filteredArrayUsingPredicate:intersectPredicate];

你在使用你的回答来试图回答问题并评论其他答案。如果你想要回应它们,请更新你的回答,只回答问题并评论适当的答案。你的回答本身很难理解。 - Hans Roerdinkholder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接