如何以任何顺序比较两个 NSArray 的相同内容?

Posted

技术标签:

【中文标题】如何以任何顺序比较两个 NSArray 的相同内容?【英文标题】:How to compare two NSArrays for equal content in any order? 【发布时间】:2012-12-11 06:54:13 【问题描述】:

我有两个NSArrays,其中数组的对象相同,但可能位于不同的索引中。它应该打印两者都相等,而不管它们的索引如何。

NSArray *arr1 = [[NSArray alloc]initWithObjects:@"aa", @"bb", @"1", @"cc", nil];
NSArray *arr2 = [[NSArray alloc]initWithObjects:@"bb", @"cc", @"1", @"aa", nil];

if ([arr1 isEqualToArray:arr2])

    NSLog(@"Equal");

else

    NSLog(@"Not equal");

上面的代码正在打印'Not equal',但它应该打印'Equal'。我该怎么做?

【问题讨论】:

这是最好的 -> ***.com/a/15710166/1059705 这能回答你的问题吗? Compare two arrays with the same value but with a different order 【参考方案1】:

这两个数组不相等。两个数组是相等的,它们都以相同的顺序具有相同的对象。

如果你想比较而不考虑顺序,那么你需要使用两个NSSet对象。

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

if ([set1 isEqualToSet:set2]) 
    // equal

【讨论】:

备注:此方法忽略重复,例如@[@1, @2]@[@1, @1, @2, @2] 被认为是相等的。但从这个问题来看,这是否是所需的行为并不明显。【参考方案2】:

这里的大多数答案实际上不适用于相当常见的情况(请参阅他们的 cmets)。有一个非常好的数据结构可以解决这个问题:NSCountedSet。

计数的集合是无序的,但确实关心存在的项目数量,因此您最终不会得到@[1, @1, @2] == @[@1, @2, @2]

NSArray *array1 = @[@1, @1, @2];
NSArray *array2 = @[@1, @2, @2];

NSCountedSet *set1 = [[NSCountedSet alloc] initWithArray:array1];
NSCountedSet *set2 = [[NSCountedSet alloc] initWithArray:array2];

BOOL isEqual = [set1 isEqualToSet:set2];
NSLog(@"isEqual:%d", isEqual);

【讨论】:

很遗憾这个类不适合 [ios] 标签 抱歉,为什么? NSCountedSet 从 2.0 开始在 iOS 中可用:developer.apple.com/library/ios/documentation/cocoa/reference/… 刚刚意识到我的原始答案引用了 mac 文档,很抱歉造成混淆。该课程也适用于 iOS - 更新答案以更正链接。【参考方案3】:

试试这个。我正在做的是复制你的第一个数组并从第二个数组中删除复制元素。如果它为空,则它相等,否则不相等。

这比@rmaddy 解决方案的内存占用更少。您只创建一个数组而不是两个数组的副本...

NSMutableArray *copyArray;
if([arr1 count] >= [arr2 count])

    copyArray = [NSMutableArray arrayWithArray:arr1];
    [copyArray removeObjectsInArray:arr2];

else //c(arr2) > c(arr1)

    copyArray = [NSMutableArray arrayWithArray:arr2];
    [copyArray removeObjectsInArray:arr1];


if([copyArray count] != 0)
    NSLog('Not Equal');
else
    NSLog('Equal');

UPDATE1:如果您想在此之后使用arr2,那么它已被更改。您需要对其进行复制,然后在这种情况下,在内存方面它与 rmaddy 解决方案所采用的相同。但是这个解决方案仍然是优越的,因为NSSet 创建时间远远超过NSArray - source。

UPDATE2:更新以使答案更全面,以防一个数组大于另一个数组。

【讨论】:

removeObjectsInArray: 有一个 void 返回类型。这不会按原样工作。 也许您的意思是调用-removeObjectsFromArray:,然后将-count 与0 相比(有创意,我喜欢它)。 如果arr2 包含比arr1 更多的元素,则此方法错误地报告 数组相等,例如。 arr1 = @[@1, @2]arr2 = @[@1, @2, @3]。 - 为什么认为arr2被这种方法修改了? @MartinR 更新了我的答案以处理您正确指出的情况。另外,由于removeObjectsInArray 修改了数组,为了完整起见,我已经提到了它...... 仍然无法正常工作(抱歉 :-)。试试arr1 = @[@1, @1, @1]arr2 = @[@1, @2]。 - 而removeObjectsInArray 只修改接收者copyArray,而不修改参数arr1arr2【参考方案4】:

就像 rmaddy 说的,那些 NSArray 是不相等的。 试试这个:

-(BOOL)compareArrayIgnoreIndexes:(NSArray*)arrayOne toArray:(NSArray*)arrayTwo
    NSSet *setOne=[[NSSet alloc]initWithArray:arrayOne];
    NSSet *setTwo=[[NSSet alloc]initWithArray:arrayTwo];
    return [setOne isEqualToSet:setTwo];

【讨论】:

【参考方案5】:

我找到了解决方案,我们可以通过对数组元素进行排序来实现

 NSArray *arr1 = [[NSArray alloc]initWithObjects:@"a2223a",@"ab33b",@"a1acdf",@"ac23c45", nil];
    NSArray *arr11 =  [arr1 sortedArrayUsingSelector:@selector(localizedCompare:)];
    NSArray *arr2 = [[NSArray alloc]initWithObjects:@"ab33b",@"ac23c45",@"a1acdf",@"a2223a", nil];
    NSArray *arr22= [arr2 sortedArrayUsingSelector:@selector(localizedCompare:)];
    if([arr11 isEqualToArray:arr22])
    
        NSLog(@"equal");
    
    else
    
        NSLog(@"Not equal");
    

【讨论】:

@CodaFi 一旦包含两个原始数组,就不会比其他答案更重要。 @rmaddy:他正在对总共三个数组执行两种排序。告诉我这不是低效吗? @CodaFi 我在两个数组上看到了两种排序。 /*总共三个数组*/,我没有看到反对排序的论据。在大多数情况下它很昂贵(但我承认在初始排序后会有暂时的速度提升,但前提是同一个数组被排序两次)。 @CodaFi 这个“三”是哪里来的?有两个原始数组。还有两个排序数组。总共有四个数组。答案中的代码有四个数组。你为什么一直说“三”?【参考方案6】:
This can be done by using one NSMutableArray.The main point to be remembered is that the larger array should be saved in NSMutableArray. Otherwise it wont work as expected. The code is given below.

NSArray *array1 = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
NSArray *array2 = [NSArray arrayWithObjects:@"Two", @"Three", @"One", nil];
NSMutableArray *intermediate = [NSMutableArray arrayWithArray:array1];
[intermediate removeObjectsInArray:array2];
NSUInteger difference = [intermediate count];//returns the number of difference between two arrays.

【讨论】:

此解决方案与 Srikar 之前发布的解决方案相同。由于同样的原因,它不能可靠地工作,请参阅上面的我的 cmets。【参考方案7】:

另一种选择是将 NSArrays 转换为 JSON 字符串,并使用 isEqualToString 进行比较。

-(BOOL)isArray:(NSArray *)firstArray equalContentsToArray:(NSArray *)secondArray 
    if (!firstArray) 
        firstArray=@[];
    

    if (!secondArray) 
        secondArray=@[];
    

    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:firstArray options:0 error:&error];
    NSString *jsonStringOne = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    jsonData = [NSJSONSerialization dataWithJSONObject:secondArray options:0 error:&error];
    NSString *jsonStringTwo = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    BOOL isEqual=NO;

    if ([jsonStringOne isEqualToString:jsonStringTwo]) 
        isEqual=YES;
    

    return isEqual;

我很好奇所有这些方法的性能比较。

【讨论】:

以上是关于如何以任何顺序比较两个 NSArray 的相同内容?的主要内容,如果未能解决你的问题,请参考以下文章

ios开发之--比较两个数组里面的值是否相同

以任何顺序给出的相同字符集的唯一哈希?

在bash shell 上如何按字母顺序比较两个字符串 ?

如何比较两个没有顺序的具有相同属性的JSON?

如何将 NSArray 拆分为按字母顺序排列的部分以与索引表视图一起使用

如何在 Swift 中比较两个可选的 NSArray