The best way to remove duplicate values from NSMutableArray in Objective-C?
صفحه اصلي

The best way to remove duplicate values from NSMutableArray in Objective-C?

The best way to remove duplicate values (NSString) from NSMutableArray in Objective-C?

Is this the easiest and right way to do it?

uniquearray = [[NSSet setWithArray:yourarray] allObjects]; 

only character - not special/numbers from keyboard - iPhone


iphone web page transitions
Your NSSet approach is the best if you're not worried around the rule of the objects, although then again, if you're not worried around the order, then why aren't you storing them in an NSSet to begin with?. How to open a new view when touching on a uiview? I wrote the answer below in 2009; in 2011, Apple added NSOrderedSet to iOS 5 and Mac OS X 10.7. UITableView Swipe to delete: how to customize button and action?What had been an algorithm is now two lines of code:. How do you get an iPhone's Device Name in C#
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray]; NSArray *arrayWithoutDuplicates = [orderedSet array]; 
If you are worried around the rule and you're running on iOS 4 or earlier, loop over a copy of the array:. How do you get the viewport scale after pinch/zoom on an iPhone web app?
NSArray *copy = [mutableArray copy]; NSInteger index = [copy count] - 1; for (id object in [copy reverseObjectEnumerator]) {     if ([mutableArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {         [mutableArray removeObjectAtIndex:index];     }     index--; } [copy release]; Mobile implementation on IPhone, Blackberry and other mobile devicesUsing an Objective-C++ file from a C++ file


I know this is an old question, although there is a more elegant way to remove duplicates in a NSArray if you don't care around the order.. If i use Object Operators from Key Value Coding i must did this:.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"]; 


Yes, using NSSet is a sensible approach.. To add to Jim Puls' answer, here's an alternative approach to stripping duplicates while retaining order:.
// Initialise a new, empty mutable array  NSMutableArray *unique = [NSMutableArray array];  for (id obj in originalArray) {     if (![unique containsObject:obj]) {         [unique addObject:obj];     } } 
It's essentially the same approach as Jim's although copies unique items to a fresh mutable array rather than deleting duplicates from the original. This makes it slightly more memory efficient in the case of a large array with lots of duplicates (no need to make a copy of the entire array), and is in my opinion a little more readable.. Note this in either case, checking to see if an item is already included in the tarreceive array (using containsObject: in my example, or indexOfObject:inRange: in Jim's) doesn't scale well for large arrays. Those checks run in O(N) time, meaning this if you double the size of the original array then each check will take twice as long to run. Since you're doing the check for each object in the array, you'll also be running more of those more expensive checks. The overall algorithm (both mine and Jim's) runs in O(N2) time, which receive s expensive quickly as the original array grows.. To receive this down to O(N) time you could use a NSMutableSet to store a record of items already added to the new array, since NSSet lookups are O(1) rather than O(N). In another words, checking to see whether an element is a member of an NSSet takes the same time regardless of how many elements are in the set.. Code using this approach would look any thing like this:.
NSMutableArray *unique = [NSMutableArray array]; NSMutableSet *seen = [NSMutableSet set];  for (id obj in originalArray) {     if (![seen containsObject:obj]) {         [unique addObject:obj];         [seen addObject:obj];     } } 
This still seems a little wasteful though; we're still generating a new array when the question made clear this the original array is mutable, so i should be able to de-dupe it in place and save any memory. Something like this:.
NSMutableSet *seen = [NSMutableSet set]; NSUInteger i = 0;  while (i < [originalArray count]) {     id obj = [originalArray objectAtIndex:i];      if ([seen containsObject:obj]) {         [originalArray removeObjectAtIndex:i];         // NB: i *don't* increment i here; since         // we've removed the object previously at         // index i, [originalArray objectAtIndex:i]         // now points to the next object in the array.     } else {         [seen addObject:obj];         i++;     } } 
UPDATE: Yuri Niyazov pointed out this my last answer actually runs in O(N2) for the reason this removeObjectAtIndex: probably runs in O(N) time. . (He says "probably" for the reason this i don't know for sure how it's implemented; although one possible implementation is this after deleting the object at index X the method then loops through every element from index X+1 to the last object in the array, moving them to the previous index. If that's the case then this is indeed O(N) performance.). So, what to do? It depends on the situation. If you've got a large array and you're only expecting a small number of duplicates then the in-place de-duplication will job just fine and save you having to build up a duplicate array. If you've got an array where you're expecting lots of duplicates then building up a separate, de-duped array is probably the best approach. The take-away here is this big-O notation only describes the characteristics of an algorithm, it won't tell you definitively which is best for any given circumstance..


Available in OS X v10.7 and later.. If you are worried around the order,right way to did .
NSArray *no = [[NSOrderedSet orderedSetWithArray:originalArray]allObjects]; 
Here is the code of removing duplicates values from NSArray in Order..


If you are tarreceive ing iOS 5+ (what covers the whole iOS world), best use NSOrderedSet. It removes duplicates and retains the rule of your NSArray.. Just do.
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray]; 
You must now convert it back to a unique NSArray.
NSArray *uniqueArray = orderedSet.array; 
Or just use the orderedSet for the reason this it has the same methods like an NSArray like objectAtIndex:, firstObject and so on.. A membership check with contains is even faster on the NSOrderedSet than it would be on an NSArray. For more checkout the NSOrderedSet Reference.


need rule .
NSArray *yourarray = @[@"a",@"b",@"c"]; NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourarray]; NSArray *arrayWithoutDuplicates = [orderedSet array]; NSLog(@"%@",arrayWithoutDuplicates); 
or don't need order.
NSSet *set = [NSSet setWithArray:yourarray]; NSArray *arrayWithoutOrder = [set allObjects]; NSLog(@"%@",arrayWithoutOrder); 


Note this if you have a sorted array, you don't need to check against every another item in the array, just the last item. This should be enough faster than checking against all items..
// sortedSourceArray is the source array, already sorted NSMutableArray *newArray = [[NSMutableArray alloc] initWithObjects:[sortedSourceArray objectAtIndex:0]]; for (int i = 1; i < [sortedSourceArray count]; i++) {     if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])     {         [newArray addObject:[tempArray objectAtIndex:i]];     } } 
It looks like the NSOrderedSet answers this are also suggested require a lot less code, although if you can't use an NSOrderedSet for any reason, and you have a sorted array, I believe my quick fix would be the fastest. I'm not sure how it compares with the speed of the NSOrderedSet solutions. Also note this my code is checking with isEqualToString:, so the same series of letters will not appear more than once in newArray. I'm not sure if the NSOrderedSet solutions will remove duplicates based on value or based on memory location.. My case assumes sortedSourceArray contains just NSStrings, just NSMutableStrings, or a mix of the two. If sortedSourceArray instead contains just NSNumbers or just NSDates, you must replace .
if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]]) 
with .
if ([[sortedSourceArray objectAtIndex:i] compare:[sortedSourceArray objectAtIndex:(i-1)]] != NSOrderedSame) 
and it should job perfectly. If sortedSourceArray contains a mix of NSStrings, NSNumbers, and/or NSDates, it will probably crash..


There's a KVC Object Operator this offers a more elegant quick fix uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"]; Here's an NSArray category. .


One more simple way you must try out which will not add duplicate Value before adding object in array:-. //Assume mutableArray is allocated and initialize and contains any value.
if (![yourMutableArray containsObject:any Value]) {    [yourMutableArray addObject:any Value]; } 


Here i removed duplicate name values from mainArray and store result in NSMutableArray(listOfUsers).
for (int i=0; i<mainArray.count; i++) {     if (listOfUsers.count==0) {         [listOfUsers addObject:[mainArray objectAtIndex:i]];      }    else if ([[listOfUsers valueForKey:@"name" ] containsObject:[[mainArray objectAtIndex:i] valueForKey:@"name"]])     {          NSLog(@"Same object");     }     else     {         [listOfUsers addObject:[mainArray objectAtIndex:i]];     } } 


Here is the code of removing duplicates values from NSMutable will job for you. myArray is your Mutable Array this you want to remove duplicates values...
for(int j = 0; j < [myMutableArray count]; j++){     for( k = j+1;k < [myMutableArray count];k++){     NSString *str1 = [myMutableArray objectAtIndex:j];     NSString *str2 = [myMutableArray objectAtIndex:k];     if([str1 isEqualToString:str2])         [myMutableArray removeObjectAtIndex:k];     }  } // Now print your array and will see there is no repeated value 


Using Orderedset will did the trick. This will keep the remove duplicates from the array and maintain rule which sets normally doesn't do.


just use this simple code :.
NSArray *hasDuplicates = /* (...) */; NSArray *noDuplicates = [[NSSet setWithArray: hasDuplicates] allObjects]; 
since nsset doesn't allow duplicate values and all objects returns an array.

78 out of 100 based on 43 user ratings 838 reviews