我选择了一些选项:numberOfApples:Int?
,numberOfBananas:Int?
,numberOfOlives:Int?
,我想创建一个仅包含设定值的字典。有没有办法简洁地创造这个?
我最接近的是:
// These variables are hard-coded for the example's
// sake. Assume they're not known until runtime.
let numberOfApples: Int? = 2
let numberOfBananas: Int? = nil
let numberOfOlives: Int? = 5
let dict: [String:Int?] = ["Apples" : numberOfApples,
"Bananas" : numberOfBananas,
"Olives" : numberOfOlives]
而且我想决定类型:[String:Int]如此:
["Apples" : 2,
"Olives" : 5]
但是这给了我一个可选项字典并通过下标访问一个值给了我一个双包装可选项。
我意识到我可以用for-loop做到这一点,但我想知道是否有更优雅的东西。
非常感谢提前。
答案 0 :(得分:3)
就我个人而言,我会这样做(这就是我个人这样做的时候):
var dict: [String: Int] = [:]
dict["Apples"] = numberOfApples
dict["Bananas"] = numberOfBananas
dict["Olives"] = numberOfOlives
简单。明确。没有技巧。
但如果你愿意,你可以写Dictionary.flatMapValues
(继续Dictionary.mapValues
的模式)。这并不难。 (编辑:添加flattenValues()
以更接近原始问题。)
extension Dictionary {
func flatMapValues<T>(_ transform: (Value) throws -> T?) rethrows -> [Key: T] {
var result: [Key: T] = [:]
for (key, value) in self {
if let transformed = try transform(value) {
result[key] = transformed
}
}
return result
}
func flattenValues<U>() -> [Key: U] where Value == U? {
return flatMapValues { $0 }
}
}
有了这个,你可以这样做,这没关系:
let dict = [
"Apples" : numberOfApples,
"Bananas": numberOfBananas,
"Olives" : numberOfOlives
].flattenValues()
答案 1 :(得分:2)
您可以使用filter
和mapValues
。您首先filter
所有值为nil的对,然后您可以安全地强制解包该值。这会将dict类型更改为[String: Int]
。
let dict = [
"Apples": numberOfApples,
"Bananas": numberOfBananas,
"Olives": numberOfOlives
]
.filter({ $0.value != nil })
.mapValues({ $0! })
print(dict) //["Olives": 5, "Apples": 2]
答案 2 :(得分:2)
试试这个:
let numberOfApples: Int? = 5
let numberOfBananas: Int? = nil
let numberOfOlives: Int? = 5
let dict: [String: Int?] = [
"Apples": numberOfApples,
"Bananas": numberOfBananas,
"Olives": numberOfOlives
]
extension Dictionary {
func flatMapValues<U>() -> [Key: U] where Value == Optional<U> {
return reduce(into: [:]) { $0[$1.key] = $1.value }
// Keeping this line as it provides context for comments to this answer. You should delete it if you copy paste this.
// return filter { $0.value != nil } as! [Key : U]
}
}
let unwrappedDict = dict.flatMapValues()
let foo: Int?? = dict["Apples"]
let bar: Int? = unwrappedDict["Apples"]