我想每次使用字典初始化结构时。稍后,我将使用它的属性来代替字典的键和值 - 这似乎更容易。但是,当我尝试下面的代码时,它告诉我"从初始值设定项返回而不初始化所有存储的属性"和"1"。self.one' 未初始化"和"2.自我.二'未初始化"。我的问题是如何从字典中初始化结构,以便我基本上有一个包含字典内容的结构?或者如何将其转换为结构?
struct Blabla {
var one: String
var two: [Int]
init(three: [String: [Int]]) {
for i in three {
self.one = i.key
self.two = i.value
}
} ERROR! - Return from initializer without initializing all stored properties
}
struct Blabla { 变量一:字符串 变量二: [Int]
init(three: [String: [Int]]) {
one = ""
two = []
for i in three {
self.one = i.key
self.two = i.value
}
} ERROR! - Return from initializer without initializing all stored properties
}
for in
子句的运行次数可能为零,在这种情况下,结构属性将不会初始化。您必须提供默认值(如果确实需要,请发出 fatalError(。
虽然我认为您的示例是纯合成的,但无需遍历数组,您可以将属性设置为其最后一个条目。
问题是,如果three
是一个空Dictionary
,则实例属性one
和two
不会被初始化。此外,您将覆盖 for 循环每次迭代中的属性,编译器无法保证在编译时会有循环的任何迭代,因此编译器错误。
您可以通过检查字典是否实际包含至少一个键值对并将第一个键值对分配给您的属性来使初始化器失败以解决此问题。
struct Blabla {
var one: String
var two: [Int]
init?(three: [String: [Int]]) {
guard let key = three.keys.first, let value = three[key] else { return nil }
one = key
two = value
}
}
但是,您应该重新考虑您实际要实现的目标,因为在当前设置中,您的 init 输入值与结构属性不匹配。
这段代码应该编译,但以这种方式初始化结构对我来说不安全,因为:
- 它假定您的字典中包含值。
- 存储的属性将始终具有您循环访问的最后一个值。
- 为了提取值以满足编译器的要求,您需要强制解包它们。(通过达维德·帕兹托的后卫放手方法,这是可以避免的(
struct Blabla {
var one: String
var two: [Int]
init(three: [String: [Int]]) {
self.one = three.keys.first!
self.two = three[three.keys.first!]!
}
}
let input = ["pizza": [1,2]]
let l = Blabla(three: input)
如果我是你,我会让你免费获得的成员初始值设定项做它的事情,并提供一个专门的初始值设定项来处理你把字典作为输入的情况,或者将该解析移动到另一个函数/类/等......
编译器错误很明显:如果字典为空,则永远不会初始化结构成员。但是代码无论如何都没有意义,因为字典的每次迭代都会覆盖值。
也许你的意思是将字典映射到结构数组
struct Blabla {
let one: String
let two: [Int]
}
let three = ["A":[1,2], "B":[3,4]]
let blabla = three.map{Blabla(one: $0.key, two: $0.value)}
print(blabla) // [Blabla(one: "A", two: [1, 2]), Blabla(one: "B", two: [3, 4])]
var a : string
var b : [int] = []
init(_ data: [string:[int]]({
//无论你想做什么
}
}