Превращение массива отсортированного словаря обратно в словарь - PullRequest
0 голосов
/ 19 июня 2020

У меня есть словарь [String : CustomUserInfo]. Ключ - это уникальный идентификатор, а значение - это настраиваемый объект, содержащий информацию о пользователе, например displayName. Пользовательский объект CustomUserInfo соответствует Comparable и Hashable.

Я ищу строку и хочу получить только три пары значений ключа.

Сначала я фильтрую словарь по displayName. Это дает мне новый словарь со всеми парами значений ключа, которые равны или больше той строки, которую я ищу.

Во-вторых, я сортирую словарь по displayName, что дает мне массив. Каждый элемент содержит пару значений ключа.

Если в массиве больше трех элементов, я удаляю остальные. Это оставляет мне массив из трех элементов.

Проблема в том, как мне преобразовать этот массив обратно в словарь?

Альтернатива: есть ли способ изменить код в закрытии после .filter, чтобы вернуть только три наиболее релевантных результата? Пропуск всего цикла туда и обратно к массиву и обратно к словарю.

Мне это нужно, потому что часть моего кода требует доступа к объектам CustomUserInfo по его ключу.

Вот упрощенная версия моего кода для детской площадки:

import UIKit

    //MARK: - Struct containing the static user dictionary.

    struct Users {
        static var users: [String : CustomUserInfo] = [

        "cjry" : CustomUserInfo(displayName: "Luke"),
        "sorg" : CustomUserInfo(displayName: "Leia"),
        "vhue" : CustomUserInfo(displayName: "Yoda"),
        "sjdy" : CustomUserInfo(displayName: "Vader"),
        "vgdr" : CustomUserInfo(displayName: "Chewbacca"),
        "awdr" : CustomUserInfo(displayName: "Han")
    ]
}

//MARK: - CustomUserInfo object

struct CustomUserInfo {
    var displayName: String
}

extension CustomUserInfo: Comparable, Hashable {
    static func < (lhs: CustomUserInfo, rhs: CustomUserInfo) -> Bool {
        return lhs.displayName.lowercased() < rhs.displayName.lowercased()
    }
}

//MARK: - The search by string method.

func searchUsers(by searchString: String) {

    let searchString = searchString.lowercased()

    let filteredUsers = Users.users.filter { $0.1.displayName.lowercased() >= searchString }
    var sortedUsers = filteredUsers.sorted { $0.1 < $1.1  }
    if sortedUsers.count > 3 {
        sortedUsers.removeLast(sortedUsers.count - 3)
    }

    //sortedUsers is of type [Dictionary<String, CustomUserInfo>.Element] but needs to be [String : CustomUserInfo]
    print(sortedUsers)

}

searchUsers(by: "Ha")

1 Ответ

1 голос
/ 19 июня 2020

Вы можете использовать reduce, чтобы преобразовать его обратно в словарь, с некоторыми другими изменениями я бы написал функцию как

func searchUsers(by searchString: String) {
    let searchString = searchString.lowercased()

    let result = Users.users.filter { $0.1.displayName.lowercased() >= searchString }
        .sorted { $0.1 < $1.1 }
        .prefix(3)
        .reduce(into: [:]) { $0[$1.key] = $1.value }

    print(result)
}
...