Swift 从选项创建字典

Swift 从选项创建字典,swift,dictionary,Swift,Dictionary,我有一些选项:numberOfApples:Int?,numberofpananas: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 numbe

我有一些选项:
numberOfApples:Int?
numberofpananas: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循环来实现这一点,但我想知道是否还有更优雅的东西


非常感谢。

您可以使用
过滤器
映射值
。首先过滤值不为零的所有对,然后可以安全地强制展开值。这会将dict类型更改为
[String:Int]

let dict = [
        "Apples": numberOfApples,
        "Bananas": numberOfBananas,
        "Olives": numberOfOlives
    ]
    .filter({ $0.value != nil })
    .mapValues({ $0! })
print(dict) //["Olives": 5, "Apples": 2]

您可以使用
过滤器
映射值
。首先过滤值不为零的所有对,然后可以安全地强制展开值。这会将dict类型更改为
[String:Int]

let dict = [
        "Apples": numberOfApples,
        "Bananas": numberOfBananas,
        "Olives": numberOfOlives
    ]
    .filter({ $0.value != nil })
    .mapValues({ $0! })
print(dict) //["Olives": 5, "Apples": 2]

就我个人而言,我会这样做(这是我个人在出现这种情况时的做法):

简单。清楚的不要耍花招

但是如果您愿意,您可以编写
Dictionary.flatMapValues
(以继续
Dictionary.mapValues
的模式)。这并不难。(编辑:添加
flattValues()
以更接近原始问题。)


就我个人而言,我会这样做(这是我个人在出现这种情况时的做法):

简单。清楚的不要耍花招

但是如果您愿意,您可以编写
Dictionary.flatMapValues
(以继续
Dictionary.mapValues
的模式)。这并不难。(编辑:添加
flattValues()
以更接近原始问题。)

试试这个:

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"]
让NumberOfApple:Int?=5.
让numberOfBananas:Int?=无
让numberOfOlives:Int?=5.
let dict:[字符串:Int?]=[
“苹果”:苹果的数量,
“香蕉”:香蕉的数量,
“橄榄”:橄榄的数量
]
扩展字典{
func flatMapValues()->[Key:U]其中Value==可选{
返回reduce(到:[:]){$0[$1.key]=$1.value}
//保留此行,因为它为对此答案的评论提供了上下文。如果复制粘贴此内容,则应将其删除。
//返回筛选器{$0.value!=nil}as![Key:U]
}
}
让unwrappedct=dict.flatMapValues()
让foo:Intdict[“苹果”]
let bar:Int?=打开包装[“苹果”]
试试这个:

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"]
让NumberOfApple:Int?=5.
让numberOfBananas:Int?=无
让numberOfOlives:Int?=5.
let dict:[字符串:Int?]=[
“苹果”:苹果的数量,
“香蕉”:香蕉的数量,
“橄榄”:橄榄的数量
]
扩展字典{
func flatMapValues()->[Key:U]其中Value==可选{
返回reduce(到:[:]){$0[$1.key]=$1.value}
//保留此行,因为它为对此答案的评论提供了上下文。如果复制粘贴此内容,则应将其删除。
//返回筛选器{$0.value!=nil}as![Key:U]
}
}
让unwrappedct=dict.flatMapValues()
让foo:Intdict[“苹果”]
let bar:Int?=打开包装[“苹果”]


您说希望它是[String:String],但您的示例中有[String:Int]一个带有可选值的字典是没有意义的,因为它违反了字典规则,即
nil
值表示缺少键。你真的需要一些东西吗?实际上没有苹果是
numberOfApples=0
@Yannick谢谢–我错了。查看更新的问题。@vadian您是对的。这只是一个例子,但我确实有一个例子,我需要一个只包含设置值的字典。比较(dupe?)你说你希望它是[String:String],但你的例子有[String:Int]一个带有可选值的字典是无意义的,因为它违反了字典规则,即
nil
值意味着缺少键。你真的需要一些东西吗?实际上没有苹果是
numberOfApples=0
@Yannick谢谢–我错了。查看更新的问题。@vadian您是对的。这只是一个例子,但我确实有一个例子,我需要一个只包含设定值的字典。比较(dupe?)谢谢你在我修复它之前回答我的问题!@MartinR提到的内容仍然存在-我正试图得到一本字典。@MartinR你是对的,对不起。我更新了答案。谢谢你在我修正之前回答我的问题!@MartinR提到的内容仍然存在-我正试图得到一本字典。@MartinR你是对的,对不起。我更新了答案。除非受到
的约束,否则使用此方法是没有意义的,其中Value==Optional
,是吗?为什么必须对其进行约束?这映射了返回可选值的任何方法。因此,它对
init?
的工作原理相同。考虑<代码> [苹果]:“1”,“香蕉”:“X”。FLATAPAPVALUE(I.IIT)< /代码>。这将创建一个任意对的字典,其中的值可以转换为Int。
flatMap
是一个通用解决方案;不仅仅是一个“删除零”的方法。是的,你就在那里。您的解决方案更通用。但是,由于问题是“如何将
[String:Int?]
转换为
[String:Int]
”,我个人更喜欢我的选项,因为它完全可以做到这一点,而用户不必为附加参数(闭包)进行推理,就可以完成他想要的操作。尽管如此,您的版本还是相当优雅(我喜欢
Int.init
example:)。两者都将进入我的
GlobalFunctions.swift
:复制以包含
flattvalues
以应用
.flatMap{$0}
。是的……有时候这种语法有点好。除非受到
的约束,否则使用这种方法是没有意义的,其中Value==Optional
,是吗?为什么必须对它进行约束?这映射了返回可选值的任何方法。因此,它对
init?
的工作原理相同。考虑<合作
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"]