最快的方法来检查一个数组是否包含另一个数组的相同对象
目标是比较两个数组,并检查它们是否包含相同的对象(尽可能快 – 数组中有很多对象)。 数组不能用isEqual:
检查isEqual:
因为它们是不同的sorting方式。
我已经尝试过这里发布的解决scheme( https://stackoverflow.com/a/1138417 – 请参阅Peter Hosey的post的最后一段代码片段)。 但是这不适用于不同的sorting数组。
我现在使用的代码如下:
+ (BOOL)arraysContainSameObjects:(NSArray *)array1 andOtherArray:(NSArray *)array2 { // quit if array count is different if ([array1 count] != [array2 count]) return NO; BOOL bothArraysContainTheSameObjects = YES; for (id objectInArray1 in array1) { BOOL objectFoundInArray2 = NO; for (id objectInArray2 in array2) { if ([objectInArray1 isEqual:objectInArray2]) { objectFoundInArray2 = YES; break; } } if (!objectFoundInArray2) { bothArraysContainTheSameObjects = NO; break; } } return bothArraysContainTheSameObjects; }
这工作,但这是两个嵌套快速枚举。 有没有办法做一个更快的比较?
根据你的代码,你对同样数量的元素是严格的,第一个数组的每个对象应该在第二个数组中,反之亦然。
最快的方法是对这两个数组进行sorting并进行比较。
例如:
NSArray *array1=@[@"a",@"b",@"c"]; NSArray *array2=@[@"c",@"b",@"a"]; array1=[array1 sortedArrayUsingSelector:@selector(compare:)]; array2=[array2 sortedArrayUsingSelector:@selector(compare:)]; if ([array1 isEqualToArray:array2]) { NSLog(@"both have same elements"); } else{ NSLog(@"both having different elements"); }
如何转换这两个数组设置和比较它们。
NSSet *set1 = [NSSet setWithArray:arr1]; NSSet *set2 = [NSSet setWithArray:arr2];
比较两者使用
if([set1 isEqualToSet:set2]) { }
使用containsObject:方法而不是迭代整个数组。
NSArray *array; array = [NSArray arrayWithObjects: @"Nicola", @"Margherita", @"Luciano", @"Silvia", nil]; if ([array containsObject: @"Nicola"]) // YES { // Do something }
喜欢这个
+ (BOOL)arraysContainSameObjects:(NSArray *)array1 andOtherArray:(NSArray *)array2 { // quit if array count is different if ([array1 count] != [array2 count]) return NO; BOOL bothArraysContainTheSameObjects = YES; for (id objectInArray1 in array1) { if (![array2 containsObject:objectInArray1]) { bothArraysContainTheSameObjects = NO; break; } } return bothArraysContainTheSameObjects; }
如果你想检查两个数组是否包含相同的重复项,只需使用NSCountedSet。 它就像一个NSSet,但是这个集合中的每个对象都有一个计数,告诉你它多久添加一次。 所以
BOOL same = (array1.count == array2.count); if (same && array.count > 0) { NSCountedSet* set1 = [[NSCountedSet alloc] initWithArray:array1]; NSCountedSet* set2 = [[NSCountedSet alloc] initWithArray:array2]; same = ([set1 isEqual: set2]); }
不pipe你怎么做,这将是非常耗时的,所以你可以考虑是否有特殊情况可以更快地处理。 这些数组通常是相同的,或者几乎相同,或者99%的时间是不同的,99%的时间是array1的随机元素不在array2中? 数组是否经常被sorting? 在这种情况下,可以检查相同位置是否有相同的对象,然后只考虑那些不相同的对象。 如果一个数组包含对象a,b,c,d,e,另一个包含a,b,x,d,y,则只需要比较数组[c,e]和[x,y]。
试图让接受的答案工作,但它不是最适合我的情况。
我find了这个答案 ,所有的功劳都归功于@joel kravets的方法。
基本上使用比较器sorting使您可以更容易地使用对象进行sorting – 因此,我尝试使用上述解决scheme时遇到的问题。
NSArray * array1 = [NSArray arrayWithArray:users]; NSArray * array2 = [NSArray arrayWithArray:threadUsers]; id mySort = ^(BUser * user1, BUser * user2){ return [user1.name compare:user2.name]; }; array1 = [array1 sortedArrayUsingComparator:mySort]; array2 = [array2 sortedArrayUsingComparator:mySort]; if ([array1 isEqualToArray:array2]) { NSLog(@"both are same"); } else{ NSLog(@"both are different"); }
以前我曾尝试使用上面的其他答案,使用break来循环,但最终这个答案是最简单的,可能是由于它的速度,最后我们有if语句,允许我们把代码依赖于如果他们是相同或不同的。
感谢Anoop让我走上正轨,Joel帮助我收紧效率
[docTypes containsObject:@"Object"];
它会适合你的需求。 早到它将返回布尔值。
这样的复杂性是O(N ^ 2),如果你遵循这种方法,你不能以较低的复杂性来做到这一点。 而如果对两个数组进行sorting然后进行比较,则可以用O(N log(N))来完成。 将它们sorting后,这样做将使用isEqualToArray:在其他N个操作中执行。
NSArray *filtered = [someArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"someParamter == %@", paramValue]]]; if (filtered.count) { }
主要的好处是你可以使用它的任何types的对象:自定义,系统,NSDictionary。 例如我需要知道的是我的UINavigationController的堆栈包含MySearchResultsVC和MyTopMenuItemsVC或不:
NSArray *filtered = [self.navigationController.viewControllers filteredArrayUsingPredicate: [NSPredicate predicateWithFormat:@"class IN %@", [NSArray arrayWithObjects: [MySearchResultsVC class], [MyTopMenuItemsVC class], nil]]]; if (filtered) { /* ok, now we can handle it! */ }
我知道这是晚了,但我只想分享我做了什么..
NSString *stringArr1 = [NSString stringWithFormat:@"%@", array1]; NSString *stringArr2 = [NSString stringWithFormat:@"%@", array2]; if ([stringArr1 isEqual: stringArr2]) NSLog(@"identical"); else NSLog(@"not");
这就像比较“@ [@ 1,@ 2,@ 3,@ 4]”==“[@ 3,@ 2,@ 1,@ 4]” ,这显然是错误的..
我想这会做:
[array1 isEqualToArray:array2];
返回bool;