如何在Swift中转换valueForKeyPath

3

我的旧的Objective-C函数是

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

我该如何在Swift中进行转换?我试着做了这样的尝试,但它会崩溃。提示为“无法将类型为 'Swift.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 解决这个问题吗?我只是想通过 username 属性在 users 数组中找出不同的用户。
编辑* 暴力解法。
    static func getNumberOfDistinctUsers(users: [ICEPKReferenceDataUser]) -> Int {

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

4

像您想的那样,您可以使用简单的“map”函数来简化代码:

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

这是因为您可以使用任何其他序列初始化Set

我在其中添加了lazy,以避免创建额外的数组副本。它可以带或不带,但我认为这样更加内存高效。Array.map会创建另一个Arrayarray.lazy.map返回一个惰性集合,按请求计算值。

话虽如此,我不知道我的方法是否比你的“暴力”方法更好。很难说哪个更容易阅读或维护。我喜欢map方法,但这可能是一种权衡(例如,我必须知道添加lazy,否则如果这是一个大数组,我可能会分配大量内存)。您的代码非常清楚地说明了发生了什么,所以我认为没有必须解决的问题。

如果您真的想使用KVC,则需要将数组转换为NSArray,而不是AnyObject,但我认为上面的代码要快得多,而且在我看来更清晰、更简单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接