Reputation: 3803
My old function in objective c is
+ (NSUInteger)getNumberOfDistinctUsers:(NSArray *)users {
NSArray* usersAfterPredicate = [users valueForKeyPath:@"@distinctUnionOfObjects.userName"];
return [usersAfterPredicate count]; }
How do I convert this in swift, I was trying to something like this but its crashing "Could not cast value of type 'Swift.Array'to 'Swift.AnyObject'"
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
var retval : Int = 0
if let usersAfterPredicate = (users as! AnyObject).valueForKeyPath("@distinctUnionOfObjects.userName") {
retval = usersAfterPredicate.count
}
return retval
}
Can I solve this problem using filter, map or Reduce? I am just trying to find out distint users in users array using the property username.
Edit* brute force way
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
var retvalSet : Set<String> = []
for user in users {
retvalSet.insert(user.userName)
}
return retvalSet.count
}
Upvotes: 3
Views: 2921
Reputation: 299345
As you suspect, you can simplify the code with a simple map:
static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {
return Set(users.lazy.map{$0.userName}).count
}
This uses the fact that you can initialize a Set
using any other sequence.
I added lazy
in there to avoid creating an extra copy of the array. It'll work with or without, but I expect it to be much more memory efficient this way. Array.map
creates another Array
. array.lazy.map
return a lazy collection that computes values as requested.
That said, I don't know that my approach is dramatically better than your "brute-force" way. It's not obvious which is easer to read or maintain. I have a fondness for the map approach, but it can be a tradeoff (I had to know to add lazy
for instance, or I could have allocated significant memory if this were a large array). Your code makes it very clear what's going on, so I don't think there's any problem that has to be solved there.
If you really wanted to use KVC, you'd need to convert your array to an NSArray
, not an AnyObject
, but I suspect that the above code is much faster, and is clearer and simpler, too, IMO.
Upvotes: 4