在Swift中定义嵌套字典

在Swift中定义嵌套字典,swift,dictionary,Swift,Dictionary,在下面的代码中,我得到一个错误[String:Double]不符合Hashable。我该怎么做 我看到了与Hashable协议不一致的问题,但我想知道为什么会出现这种情况,另一种方法是有效的。是否只需要字典中的“Key”就可以确认为Hashable?一些解释会有帮助 enum someEnumType { case First(String, (Int, Int)->Int) case Second (String, Int) } // var operations

在下面的代码中,我得到一个错误
[String:Double]不符合Hashable
。我该怎么做

我看到了与Hashable协议不一致的问题,但我想知道为什么会出现这种情况,另一种方法是有效的。是否只需要字典中的“Key”就可以确认为Hashable?一些解释会有帮助

enum someEnumType {
    case First(String, (Int, Int)->Int)
    case Second (String, Int)
}
//    var operations = [someEnumType : [String : Double]]();  <--- This syntax Works

var operations = [[String : Double] : someEnumType  ]();  <--- But this does not work, ideally - i want this.
enum someEnumType{
大小写优先(字符串,(Int,Int)->Int)
第二个大小写(字符串,Int)
}

//var operations=[someEnumType:[String:Double]]() 是的,密钥需要是可散列的

字典也称为†哈希表;它们通过散列键来工作。因此,是的,它确实需要是可散列的。由于关键是按键查找值,因此该值不存在


†严格地说,可以实现一个没有散列的字典,但实际上编程语言中称为字典的数据结构通常被理解为散列映射。同样在Swift中,
字典
文档将其指定为“基于哈希的映射”。

您应该能够通过使用NSString而不是String来解决此问题。

如果您是正确的,则只有字典的密钥必须符合哈希协议

“我该怎么解决这个问题?” 使用字典的最直接方法可能是定义自己的键类型。一个
struct
在这里是有意义的;它提供的值语义与您的
[String:Double]
可能的键提供的值语义相同,并且易于定义:

struct MyKey {
    let myString: String
    let myDouble: Double
}
当然,它必须是可哈希的,才能用作字典键,因此我们添加了
hashable
一致性:

struct MyKey: Hashable {
    let myString: String
    let myDouble: Double

    var hashValue: Int {
        return self.myString.hashValue ^ self.myDouble.hashValue
    }
}
我在那里做了一个可爱的小技巧来计算这个键类型的“唯一ish”散列值:只是字符串和double散列值的异或。我不能保证唯一性,但在大多数情况下它应该足够好。计算一个更好的散列值是一个练习,如果你愿意的话,我将留给你(但它会像这样很好地工作)

最后,要符合
Hashable
,还必须符合
equalable
。在本例中,我们只需检查一个键的属性是否与另一个匹配,以确定键是否相等。全面实施:

struct MyKey: Hashable {
    let myString: String
    let myDouble: Double

    var hashValue: Int {
        return self.myString.hashValue ^ self.myDouble.hashValue
    }
}

func ==(lhs: MyKey, rhs: MyKey) -> Bool {
    return lhs.myString == rhs.myString && lhs.myDouble == rhs.myDouble
}

现在,您可以这样定义词典:

var operations = [MyKey : someEnumType  ]()
let myFirstKey = MyKey(myString: "Hello", myDouble: 1.0)
operations[myFirstKey] = someEnumType
并添加如下条目:

var operations = [MyKey : someEnumType  ]()
let myFirstKey = MyKey(myString: "Hello", myDouble: 1.0)
operations[myFirstKey] = someEnumType