简体   繁体   English

检查数组是否包含另一个数组的相同对象的最快方法

[英]Fastest way to check if an array contains the same objects of another array

The goal is to compare two arrays as and check if they contain the same objects (as fast as possible - there are lots of objects in the arrays). 目的是比较两个数组,并检查它们是否包含相同的对象(尽可能快-数组中有很多对象)。 The arrays cannot be checked with isEqual: as they are differently sorted. 数组无法使用isEqual:进行检查,因为它们的排序方式不同。

I already tried the solution posted here ( https://stackoverflow.com/a/1138417 - see last code snippet of the post by Peter Hosey). 我已经尝试过此处发布的解决方案( https://stackoverflow.com/a/1138417-参见Peter Hosey发布的最新代码片段)。 But this doesn't work with differently sorted arrays. 但这不适用于不同排序的数组。

The code I'm using now is the following: 我现在使用的代码如下:

+ (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;
}

This works, but those are two nested fast enumerations. 这是可行的,但它们是两个嵌套的快速枚举。 Is there a way to do a faster comparison? 有没有一种方法可以进行更快的比较?

As per your code, you are strict to same number of elements and each object of first array should be there in second array and vice versa. 根据您的代码,您必须严格限制元素的数量,并且第一个数组的每个对象都应位于第二个数组中,反之亦然。

The fastest way would be to sort both the array and compare them. 最快的方法是对两个数组进行排序并进行比较。

Ex: 例如:

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");
}

How about converting both arrays to sets and comparing them. 如何将两个数组都转换为集合并进行比较。

NSSet *set1 = [NSSet setWithArray:arr1];
NSSet *set2 = [NSSet setWithArray:arr2];

Compare the two using 比较两个使用

if([set1 isEqualToSet:set2]) {

}

Use containsObject: method instead of iterating the whole array. 使用containsObject:方法,而不要迭代整个数组。

NSArray *array;
array = [NSArray arrayWithObjects: @"Nicola", @"Margherita",                                       @"Luciano", @"Silvia", nil];
if ([array containsObject: @"Nicola"]) // YES
  {
    // Do something
  }

like this 像这样

+ (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;
}

Tried to get the accepted answer working but it wasn't quite the best fit for my situation. 试图使被接受的答案起作用,但它并不是最适合我的情况。

I found this answer and all credit goes to @joel kravets for the method. 我找到了这个答案 ,所有方法归功于@joel kravets。

Basically sorting using a comparator enables you to sort using objects more easily - hence the problem I was facing when trying to use the above solution. 基本上,使用比较器进行排序使您可以更轻松地使用对象进行排序-因此,当我尝试使用上述解决方案时遇到了问题。

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");
}

Previously I had tried to use other answers like those above, using break to go through loops but in the end this answer came out easiest probably due to its speed and also that in the end we have the if statement allowing us to put code depending on if they are the same or different. 以前,我曾尝试使用上述其他答案,使用break来遍历循环,但是最后,由于速度快,最容易得出这个答案,最后,我们有了if语句,使我们可以根据如果它们相同或不同。

Thanks to Anoop for getting me on the right track and Joel for helping me to tighten the efficiency of it 感谢Anoop使我走上正确的道路,并感谢Joel帮助我提高效率

This way the complexity is O(N^2), if you follow this approach you can't do it with a lower complexity. 这样,复杂度为O(N ^ 2),如果您遵循这种方法,则无法以更低的复杂度来做到这一点。 While instead you can do it with O(N log(N)) if you sort both arrays and then compare them. 相反,如果您对两个数组都进行排序然后进行比较,则可以使用O(N log(N))来实现。 This way after having them sorted you will do it using isEqualToArray: in other N operations. 这样,在对它们进行排序后,您将在其他N个操作中使用isEqualToArray:进行此操作。

[docTypes containsObject:@"Object"];

It will works for your req. 它将适合您的要求。 As early as fast it will return boolean value for it. 它将尽快返回布尔值。

NSArray *filtered = [someArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"someParamter == %@", paramValue]]];
if (filtered.count) {

}

the main plus is you can use it for any kind of objects: custom, system, NSDictionary. 主要优点是您可以将其用于任何类型的对象:自定义,系统,NSDictionary。 for example I need to know is my UINavigationController's stack contains MySearchResultsVC and MyTopMenuItemsVC or not: 例如,我需要知道我的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! */
}

If you want to check whether both arrays contain the same duplicates, just use NSCountedSet. 如果要检查两个数组是否包含相同的重复项,请使用NSCountedSet。 It's like an NSSet, but each object in the set also has a count telling you how often it has been added. 这就像一个NSSet,但是集合中的每个对象也都有一个计数,告诉您它被添加的频率。 So 所以

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

No matter how you do it, this will be time consuming, so you might consider if there are special cases that can be handled quicker. 无论您怎么做,这都会很耗时,因此您可能会考虑是否有可以更快处理的特殊情况。 Are these arrays usually the same, or almost the same, or is it true 99% of the time that they are different and that 99% of the time a random element of array1 is not in array2? 这些数组通常是相同的还是几乎相同的,或者是在99%的时间内它们确实是不同的,并且在99%的时间中array1中的随机元素不在array2中是真的吗? Are the arrays often sorted? 数组经常排序吗? In that case, you could check whether there are identical objects in identical positions, and then consider only those objects that are not the same. 在这种情况下,您可以检查相同位置的对象是否相同,然后仅考虑不相同的对象。 If one array contains objects a, b, c, d, e and the other contains a, b, x, d, y, then you only need to compare the array [c, e] vs. [x, y]. 如果一个数组包含对象a,b,c,d,e,而另一个数组包含a,b,x,d,y,则只需要比较数组[c,e]与[x,y]。

I know it's late but i just wanna share what i did.. 我知道已经晚了,但我只想分享我的所作所为。

NSString *stringArr1 = [NSString stringWithFormat:@"%@", array1];
NSString *stringArr2 = [NSString stringWithFormat:@"%@", array2];

if ([stringArr1 isEqual: stringArr2])
    NSLog(@"identical");
else
    NSLog(@"not");

this is just like comparing "@[@1,@2,@3,@4]" == "[@3,@2,@1,@4]" .. which is obviously false.. 这就像比较“ @ [@ 1,@ 2,@ 3,@ 4]” ==“ [@ 3,@ 2,@ 1,@ 4]” ..这显然是错误的。

i guess this will do: 我想这会做:

[array1 isEqualToArray:array2];

returns bool; 返回布尔值;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 快速检查对象数组是否包含另一个数组的对象 - Swift check if an array of objects contains an object of another array 检查一个数组是否包含 swift 中另一个数组的元素 - Check if an array contains elements of another array in swift 检查数组是否包含Swift中另一个的所有元素 - Check if an array contains all elements of another in Swift 获取NSString中所有大写字母的NSRange对象数组的最快方法? - Fastest way to get array of NSRange objects for all uppercase letters in an NSString? iOS Swift:符合协议的对象数组:如何检查数组是否包含 - iOS Swift: Array of Objects conforming to a Protocol: How to check if array contains 如何以最快的方式检查我的 nsarray 是否包含另一个 nsarray 元素 IOS - How to check my nsarray contains another nsarray element or not in fastest way IOS 检查对象数组中键的值是否与iOS相同? - Check if the value of key in an array of objects is same iOS? 检查自定义对象数组是否包含具有特定日期的对象 - Check if an array of custom objects contains an object with a certain date 想要检查数组是包含全部对象还是仅包含某些对象-iOS - Want to check whether an array contains all or just certain objects - iOS 检查数组是否包含元素 - Check if array contains element
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM