Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone - getting unique values from NSArray object

I have an NSArray formed with objects of a custom class. The class has 3 (city, state, zip) string properties. I would like to get all unique state values from the array.

I did read through the NSPredicate class but couldn't make much of how to use it in this case. The only examples I could find were for string operations.

Can someone please help me out?

like image 803
lostInTransit Avatar asked Sep 17 '09 15:09

lostInTransit


People also ask

What's a difference between NSArray and NSSet?

The main difference is that NSArray is for an ordered collection and NSSet is for an unordered collection. There are several articles out there that talk about the difference in speed between the two, like this one. If you're iterating through an unordered collection, NSSet is great.

Can NSArray contain nil?

arrays can't contain nil.

Can we use NSArray in Swift?

In Swift, the NSArray class conforms to the ArrayLiteralConvertible protocol, which allows it to be initialized with array literals. For more information about object literals in Swift, see Literal Expression in The Swift Programming Language (Swift 4.1).

What is NSSet in Swift?

NSSet is “toll-free bridged” with its Core Foundation counterpart, CFSet . See Toll-Free Bridging for more information on toll-free bridging. In Swift, use this class instead of a Set constant in cases where you require reference semantics.


2 Answers

Take a look at keypaths. They are super powerful and I use them instead of NSPredicate classes most of the time. Here is how you would use them in your example...

NSArray *uniqueStates; uniqueStates = [customObjects valueForKeyPath:@"@distinctUnionOfObjects.state"]; 

Note the use of valueForKeyPath instead of valueForKey.

Here is a more detailed/contrived example...

NSDictionary *arnold = [NSDictionary dictionaryWithObjectsAndKeys:@"arnold", @"name", @"california", @"state", nil]; NSDictionary *jimmy = [NSDictionary dictionaryWithObjectsAndKeys:@"jimmy", @"name", @"new york", @"state", nil]; NSDictionary *henry = [NSDictionary dictionaryWithObjectsAndKeys:@"henry", @"name", @"michigan", @"state", nil]; NSDictionary *woz = [NSDictionary dictionaryWithObjectsAndKeys:@"woz", @"name", @"california", @"state", nil];  NSArray *people = [NSArray arrayWithObjects:arnold, jimmy, henry, woz, nil];  NSLog(@"Unique States:\n %@", [people valueForKeyPath:@"@distinctUnionOfObjects.state"]);  // OUTPUT // Unique States: // "california", // "michigan", // "new york" 
like image 163
probablyCorey Avatar answered Sep 21 '22 23:09

probablyCorey


The totally simple one liner:

NSSet *uniqueStates = [NSSet setWithArray:[myArrayOfCustomObjects valueForKey:@"state"]]; 

The trick is the valueForKey: method of NSArray. That will iterate through your array (myArrayOfCustomObjects), call the -state method on each object, and build an array of the results. We then create an NSSet with the resulting array of states to remove duplicates.


Starting with iOS 5 and OS X 10.7, there's a new class that can do this as well: NSOrderedSet. The advantage of an ordered set is that it will remove any duplicates, but also maintain relative order.

NSArray *states = [myArrayOfCustomObjects valueForKey:@"state"]; NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:states]; NSSet *uniqueStates = [orderedSet set]; 
like image 40
Dave DeLong Avatar answered Sep 20 '22 23:09

Dave DeLong