2015-09-02 69 views
3

我的老功能的目標C是如何valueForKeyPath轉換中迅速

+ (NSUInteger)getNumberOfDistinctUsers:(NSArray *)users { 
NSArray* usersAfterPredicate = [users valueForKeyPath:@"@distinctUnionOfObjects.userName"]; 
return [usersAfterPredicate count]; } 

如何轉換這迅速,我想是這樣的,但它的崩潰「無法投類型的值「雨燕.Array'到'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 
} 

我可以使用filter,map或Reduce來解決這個問題嗎?我只是試圖找出使用屬性用戶名的用戶數組distint用戶。

編輯*蠻力方式

static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int { 

    var retvalSet : Set<String> = [] 
    for user in users { 
     retvalSet.insert(user.userName) 
    } 
    return retvalSet.count 
} 

回答

4

當你懷疑,可以簡單地用一個簡單的地圖代碼:

static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int { 
    return Set(users.lazy.map{$0.userName}).count 
} 

它使用的事實,你可以使用任何其他初始化Set序列。

我在那裏添加了lazy以避免創建數組的額外副本。它可以工作,也可以不工作,但我希望它能以這種方式提高內存使用效率。 Array.map創建另一個Arrayarray.lazy.map返回一個按要求計算值的惰性集合。

這就是說,我不知道我的方法比你的「蠻力」方式好得多。閱讀或維護哪個更容易,這並不明顯。我喜歡地圖的方法,但它可以是一個折衷(我必須知道,例如添加lazy,或者如果這是一個大陣列,我可以分配顯着的內存)。你的代碼很清楚發生了什麼事情,所以我不認爲有任何問題需要解決。

如果你真的想使用KVC,你需要你的數組轉換爲NSArray,不是AnyObject,但我懷疑,上面的代碼的速度要快得多,並且更清晰,更簡單,也IMO。