Resolving too many else-if statements in Swift 3

Viewed 1375

Problem: Given the inputs of the function, test each user to make sure they conform to the following conditions: 1. Each user in the users array cannot share a chatroom with the current user. (The Chatroom object has two properties 'firstUserId', and 'secondUserId'.
2. Each user in the users array is not the current user. 3. Each user in the users array is within 5 mile radius of current user.

At the call sight of the completion handler, I check if a User object has a value of true, if so, I show it to the current user as a potential match.

Now, I quickly brute forced this solution, but cringe every time I look at it. It just seems very inefficient. Any tips on a more elegant solution is much appreciated!

typealias validUsersCompletionHandler = (_ users: [User: Bool]) -> Void

private func validateNewUsers(currentUser: User, users: [User], chatrooms: [Chatroom], completionHandler: validUsersCompletionHandler?) {

    var results: [User: Bool] = [:]

    let currentUserCoords = CLLocation(latitude: currentUser.latitude, longitude: currentUser.longitude)

    for user in users {
        let newUserCoords = CLLocation(latitude: user.latitude, longitude: user.longitude)
        let distance = currentUserCoords.distance(from: newUserCoords)
        // // 1 mile = 1609 meters, 8046.72 = 5 miles.
        for chatroom in chatrooms {
            if currentUser.id == chatroom.firstUserId && user.id == chatroom.secondUserId {
                results[user] = false
            } else if currentUser.id == chatroom.secondUserId && user.id == chatroom.firstUserId {
                results[user] =  false
            } else if user.id == currentUser.id {
                results[user] = false
            } else if distance > 8046.72 {
                results[user] = false
            } else {
                results[user] = true
            }
        }
    }
    completionHandler?(results)
}

// ************************************************************************

// Below is my revised version of the method. Slightly more elegant I suppose?

// ************************************************************************

typealias validUsersCompletionHandler = (_ users: [User: Bool]) -> Void

private func validateNewUsers(currentUser: User, users: [User], chatrooms: [Chatroom], completionHandler: validUsersCompletionHandler?) {

    var results: [User: Bool] = [:]

    var isInRange = false

    var distance: Double = 0 {
        didSet {
            if distance > 8046.72 {
                isInRange = false
            } else {
                isInRange = true
            }
        }
    }

    let currentUserCoords = CLLocation(latitude: currentUser.latitude, longitude: currentUser.longitude)

    let currentUserId = currentUser.id

    for user in users {

        let userId = user.id

        let newUserCoords = CLLocation(latitude: user.latitude, longitude: user.longitude)

        distance = currentUserCoords.distance(from: newUserCoords)
        // // 1 mile = 1609 meters, 8046.72 = 5 miles.

        for chatroom in chatrooms {

            switch (currentUserId, userId, isInRange) {

            case (chatroom.firstUserId,chatroom.secondUserId, _), (_, _, false),(chatroom.secondUserId, chatroom.firstUserId, _), (_, currentUserId, _): results[user] = false

            default: results[user] = true

            }
        }

    }

    completionHandler?(results)

}

}

2 Answers
Related