简体   繁体   English

如何在 Swift 中使用字典初始化结构

[英]How to initialize a struct with dictionaries in Swift

I want to initialize every time a struct with dictionaries.我想每次初始化一个带有字典的结构。 Later, I'm going to use its properties instead a dictionary's keys and values - it seems rather easier.稍后,我将使用它的属性而不是字典的键和值——这似乎更容易。 However, when I try the code below, it tells me that "Return from initializer without initializing all stored properties" and "1. 'self.one' not initialized" and "2. 'self.two' not initialized".但是,当我尝试下面的代码时,它告诉我“从初始化程序返回而不初始化所有存储的属性”和“1. 'self.one' 未初始化”和“2. 'self.two' 未初始化”。 My question is how to initialize a struct from a dictionary, so that I have basically a struct with the contents of the dictionary?我的问题是如何从字典初始化结构,以便我基本上有一个包含字典内容的结构? Or how to transform it into struct?或者如何将其转换为结构?

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 { var one: String var two: [Int] 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 clause may have zero runs, in which case struct properties will not be initialized. for in子句可能有零次运行,在这种情况下,结构属性将不会被初始化。 You have to provide default values (or emit fatalError if you really need to).您必须提供默认值(如果确实需要,则发出致命错误)。

While I think your example is pure synthetical, there is no need to loop through array, you can set properties to its last entry.虽然我认为您的示例是纯合成的,但无需遍历数组,您可以将属性设置为其最后一个条目。

This code should compile, but it feels unsafe to me to initialize a Struct in this way because:这段代码应该可以编译,但我觉得以这种方式初始化 Struct 是不安全的,因为:

  • It assume your dictionary has values in it.它假设您的字典中有值。
  • Your stored properties will always have the last value you looped through.您存储的属性将始终具有您循环访问的最后一个值。
  • In order to pull values out to satisfy the compiler you need to force unwrap them.为了拉出值以满足编译器,您需要强制解包它们。 (With Dávid Pásztor's guard-letting approach, this can be avoided) (通过 Dávid Pásztor 的放哨方法,可以避免这种情况)
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)

If I were you I would let the memberwise initializer that you get for free do its thing and provide either a specialized initializer to handle your case of taking a Dictionary as input or move that parsing to another function/class/etc....如果我是你,我会让你免费获得的成员初始化器做它的事情,并提供一个专门的初始化器来处理你将字典作为输入的情况,或者将解析移动到另一个函数/类/等......

The issues is that if three is an empty Dictionary , the instance properties one and two don't get initialised.问题是如果three是一个空的Dictionary ,实例属性onetwo不会被初始化。 Also, you are overwriting the properties in each iteration of the for loop and the compiler cannot guarantee that there will be any iterations of the loop in compile-time, hence the compiler error.此外,您在 for 循环的每次迭代中都覆盖了属性,编译器无法保证在编译时会有任何循环迭代,因此会出现编译器错误。

You could make the initialiser failable to account for this by checking that the dictionary actually contains at least one key-value pair and assigning that first key-value pair to your properties.您可以通过检查字典是否实际包含至少一个键值对并将第一个键值对分配给您的属性来使初始化程序无法解决这个问题。

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
    }
}

However, you should rethink what it is that you are actually trying to achieve, since with your current setup you have a mismatch between your init input values and the properties of your struct.但是,您应该重新考虑您实际尝试实现的目标,因为在您当前的设置中,您的 init 输入值与结构的属性不匹配。

The compiler error is clear: If the dictionary is empty the struct members are never initialized.编译器错误很明显:如果字典为空,则永远不会初始化结构成员。 But the code makes no sense anyway as each iteration of the dictionary overwrites the values.但是代码没有任何意义,因为字典的每次迭代都会覆盖值。

Maybe you mean to map the dictionary to an array of the struct也许您的意思是将字典映射到结构数组

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])]

i find out that when you are initialising an empty object of some struct then you can use this我发现当您初始化某个结构的空对象时,您可以使用它

var nameofvar = Blabla([:]) var nameofvar = Blabla([:])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM