Как извлечь подмножество быстрого словаря 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)]