Как извлечь подмножество быстрого словаря 3

Я просмотрел здесь методы, но не могу найти то, что ищу. Я новичок в Swift. Я хотел бы извлечь подмножество из словаря на основе набора ключевых значений, желательно без цикла.

Например, если мой ключ Set имеет тип Set<String> и у меня есть словарь типа Dictionary<String, CustomObject>Я хотел бы создать новый словарь типа Dictionary<String, CustomObject> который содержит только пары ключ-значение, связанные с ключами в наборе строк.

Я вижу, что я мог бы сделать это с for цикл, инициализируя новый Dictionary<String, CustomObj>()проверка, содержит ли исходный словарь значение для каждой строки в наборе, и добавление пар ключ-значение в новый словарь. Мне интересно, если есть более эффективный / элегантный способ сделать это как бы то ни было.

Я был бы открыт для поиска подмножества с массивом строк вместо набора, если есть лучший способ сделать это с помощью массива ключей.

Большое спасибо!

2 ответа

Решение

Ваше предположение верно, есть более сжатый / быстрый способ выполнить то, что вам нужно.

Например, вы можете сделать это через reduceконцепция функционального программирования, доступная в Swift:

let subDict = originalDict.reduce([String: CustomObject]()) {
    guard mySet.contains($1.key) else { return $0 }
    var d = $0
    d[$1.key] = $1.value
    return d
}

Или, в два этапа, сначала отфильтровывая допустимые элементы, а затем создайте обратно словарь с отфильтрованными элементами:

let filteredDict = originalDict.filter { mySet.contains($0.key) }
    .reduce([CustomObject]()){ var d = $0; d[$1.key]=$1.value; return d }

forEach также может быть использован для построения отфильтрованного словаря:

var filteredDict = [CustomObject]()
mySet.forEach { filteredDict[$0] = originalDict[$0] }

, однако результат был бы хорош, если бы он был неизменным:

let filteredDict: [String:CustomObject] = { 
    var result = [String:CustomObject]()
    mySet.forEach { filteredDict2[$0] = originalDict[$0] }
    return result
}()

Swift 5 - Вы можете сделать это очень просто:

let subsetDict = originalDict.filter({ mySet.contains($0.key)})

Результатом является новый словарь того же типа, что и исходный, но содержащий только пары ключ-значение, соответствующие ключам в mySet.

Тип манекена:

struct CustomObject {
    let foo: Int
    init(_ foo: Int) { self.foo = foo }
}

В случае, если вы хотите изменить исходный словарь (вместо создания нового) способом "пересечения", основываясь на заданном наборе ключей:

let keySet = Set(["foo", "baz"])
var dict = ["foo": CustomObject(1), "bar": CustomObject(2),
            "baz": CustomObject(3), "bax": CustomObject(4)]

Set(dict.keys).subtracting(keySet).forEach { dict.removeValue(forKey: $0) }

print(dict) // ["foo": CustomObject(foo: 1), "baz": CustomObject(foo: 3)]
Другие вопросы по тегам