如何在swift中转换valueForKeyPath

时间:2015-09-02 19:17:23

标签: objective-c swift functional-programming

我在目标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数组中的distint用户。

编辑*强力方式

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

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

1 个答案:

答案 0 :(得分:4)

如您所料,您可以使用简单的地图简化代码:

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

这使用了您可以使用任何其他序列初始化Set的事实。

我在其中添加了lazy以避免创建数组的额外副本。它可以使用或不使用,但我希望通过这种方式可以提高内存效率。 Array.map创建了另一个Arrayarray.lazy.map返回一个惰性集合,根据请求计算值。

那就是说,我不知道我的方法比你的蛮力&#34;办法。哪个更易于阅读或维护,这一点并不明显。我喜欢地图方法,但它可以是一种权衡(例如我必须知道添加lazy,或者如果这是一个大数组我可以分配大量内存)。你的代码清楚地说明了发生了什么,所以我不认为那里有任何问题需要解决。

如果你真的想使用KVC,你需要将你的数组转换为NSArray,而不是AnyObject,但我怀疑上面的代码要快得多,而且是IMO也是更清晰,更简单。