How to compare two NSArrays for equal content in any order?
Solution 1
Those two arrays are not equal. Two arrays are equal is they both have the same objects in the same order.
If you want to compare with no regard to order then you need to use two NSSet
objects.
NSSet *set1 = [NSSet setWithArray:arr1];
NSSet *set2 = [NSSet setWithArray:arr2];
if ([set1 isEqualToSet:set2]) {
// equal
}
Solution 2
Most of the answers here actually do not work for fairly common cases (see their comments). There is a very good data structure that will solve this problem: NSCountedSet.
The counted set is unordered, but does care about the number of items present, so you don't end up with @[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);
Solution 3
Try this. What I am doing is make a copy of your first array & remove copy elements from the second array. If its empty then its equal, else not equal.
This has lesser memory foot print than @rmaddy solution. You create a duplicate of only one array not both arrays...
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: If you want to use arr2
after this then its been changed. You need to make a copy of it, then in that case memory-wise its same as what rmaddy solution takes. But still this solution is superior since, NSSet
creation time is far more than NSArray
- source.
UPDATE2: Updated to make the answer more comprehensive incase one array is bigger than other.
Solution 4
Just like rmaddy said, those NSArrays are not equal. Try this:
-(BOOL)compareArrayIgnoreIndexes:(NSArray*)arrayOne toArray:(NSArray*)arrayTwo{
NSSet *setOne=[[NSSet alloc]initWithArray:arrayOne];
NSSet *setTwo=[[NSSet alloc]initWithArray:arrayTwo];
return [setOne isEqualToSet:setTwo];
}
Solution 5
I found the solution,,we can achieve that by sorting the array elements
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");
}
Ravi
Updated on January 13, 2022Comments
-
Ravi over 2 years
I have two
NSArray
s where the objects of the arrays are the same but might be in different indices. It should print both are equal irrespective of their indices.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"); }
The above code is printing
'Not equal'
but it should print'Equal'
. How can I do this? -
rmaddy over 11 years
removeObjectsInArray:
has avoid
return type. That won't work as-is. -
CodaFi over 11 yearsPerhaps you meant to call
-removeObjectsFromArray:
, then take a-count
compared to 0 (inventive, I like it). -
rmaddy over 11 years@CodaFi no more so than the other answers once you include the two original arrays.
-
CodaFi over 11 years@rmaddy: He's performing two sorts on a total of three arrays. Tell me that's not inefficient?
-
rmaddy over 11 years@CodaFi I see two sorts on two arrays.
-
CodaFi over 11 years/*a total of three arrays*/, and I see no argument against the sorting. It's expensive in most cases (but I will admit that there is a temporary speed boost after an initial sort, but only if the same array is being sorted twice).
-
Martin R over 11 yearsThis method wrongly reports arrays as equal if
arr2
contains "more" elements thanarr1
, eg.arr1 = @[@1, @2]
,arr2 = @[@1, @2, @3]
. - And why do think thatarr2
is modified by this method? -
Martin R over 11 yearsRemark: This method ignores duplicates, e.g.
@[@1, @2]
and@[@1, @1, @2, @2]
are considered equal. But it is not obvious from the question if this is the desired behaviour or not. -
Srikar Appalaraju over 11 years@MartinR updated my answer to handle the scenario you correctly pointed out. Also since
removeObjectsInArray
modifies the array inplace, I had mentioned it for the sake of completeness... -
Martin R over 11 yearsStill does not work (sorry :-). Try
arr1 = @[@1, @1, @1]
andarr2 = @[@1, @2]
. - AndremoveObjectsInArray
modifies only the receivercopyArray
, not the argumentarr1
orarr2
. -
rmaddy over 11 years@CodaFi Where is this "three" coming from? There are two original arrays. There are two more sorted arrays. That's a total of four arrays. The code in the answer has four arrays. Why do you keep saying "three"?
-
Martin R over 11 yearsThis solution is identical to Srikar's solution posted earlier. And it does not work reliably for the same reasons, see my comments above.
-
OC Rickard over 10 yearsYou could fix Martin R's question fairly easily, but What about @[@1, @1, @2], and @[@1, @2, @2]?
-
voromax over 10 yearsUnfortunately this class does not fit the [ios] tag
-
Unheilig over 10 years@rmaddy Am a bit late here, but wanted to ask: did you eventually manage to spot the 3rd one here? Thanks.
-
rmaddy over 10 years@Unheilig No and after looking at this again I still have no idea what CodaFi was referring to.
-
Unheilig over 10 years@CodaFi Hi CodaFi. Just happened to see this post and out of curiosity I tried looking at the answer here to find the hidden gem you mentioned - the 3rd sorted array. Unfortunately I have not been able to spot it. I have even tried looking at it with my eye crossed - that didn't work either. So, could you please tell me why there are 3 sorted arrays here when there are only two arrays being sorted? Thanks in advance.
-
OC Rickard over 10 yearsSorry, why? NSCountedSet has been available in iOS since 2.0: developer.apple.com/library/ios/documentation/cocoa/reference/…
-
OC Rickard over 10 yearsJust realized my original answer referenced the mac docs, so sorry for the confusion. The class is available for iOS too -- updated answer to correct the link.
-
Unheilig over 10 years@MartinR I am late here. I happened to come across this post yesterday. Was hoping to ask if you could provide me a little clarification from Ravi's answer below where CodaFi says that are 3 arrays being sorted when actually 2 are actually sorted. I have looked at it for many hours, I can't spot the 3rd one. If you know what the 3rd array is, could you please tell me where it is? Thanks in advance.
-
Martin R over 10 years@Unheilig: Actually I don't know. But Ravi's solution has the disadvantage that the objects must be comparable (as strings), so it is not so general. Using a counted set (as in another answer below) seems better to me. (Which is incidentally the same as this answer stackoverflow.com/a/15710166/1059705, but I am sure that I was not the first one.)