JuJ*_*oDi 51 dictionary tuples swift
我想知道我是否能以某种方式使用x,y对作为我字典的关键
let activeSquares = Dictionary <(x: Int, y: Int), SKShapeNode>()
但我得到错误:
Cannot convert the expression's type '<<error type>>' to type '$T1'
和错误:
Type '(x: Int, y: Int)?' does not conform to protocol 'Hashable'
那么..我们怎样才能使它符合要求?
Luk*_*kas 41
Dictionaryis 的定义struct Dictionary<KeyType : Hashable, ValueType> : ...,即密钥的类型必须符合协议Hashable.但语言指南告诉我们,协议可以通过类,结构和枚举来采用,即不是通过元组.因此,元组不能用作Dictionary键.
一种解决方法是定义一个包含两个Int(或者你想要放在元组中的任何内容)的hashable结构类型.
Mar*_*gor 18
如上面的答案所述,这是不可能的.但是您可以使用Hashable协议将元组包装为通用结构作为解决方法:
struct Two<T:Hashable,U:Hashable> : Hashable {
  let values : (T, U)
  var hashValue : Int {
      get {
          let (a,b) = values
          return a.hashValue &* 31 &+ b.hashValue
      }
  }
}
// comparison function for conforming to Equatable protocol
func ==<T:Hashable,U:Hashable>(lhs: Two<T,U>, rhs: Two<T,U>) -> Bool {
  return lhs.values == rhs.values
}
// usage:
let pair = Two(values:("C","D"))
var pairMap = Dictionary<Two<String,String>,String>()
pairMap[pair] = "A"
不需要特殊的代码或幻数来实现 Hashable
Swift 4.2中的 Hashable :
struct PairKey: Hashable {
    let first: UInt
    let second: UInt
    func hash(into hasher: inout Hasher) {
        hasher.combine(self.first)
        hasher.combine(self.second)
    }
    static func ==(lhs: PairKey, rhs: PairKey) -> Bool {
        return lhs.first == rhs.first && lhs.second == rhs.second
    }
}
更多信息: https: //nshipster.com/hashable/
小智 5
我在一个应用程序中创建了以下代码:
struct Point2D: Hashable{
    var x : CGFloat = 0.0
    var y : CGFloat = 0.0
    var hashValue: Int {
        return "(\(x),\(y))".hashValue
    }
    static func == (lhs: Point2D, rhs: Point2D) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }
}
struct Point3D: Hashable{
    var x : CGFloat = 0.0
    var y : CGFloat = 0.0
    var z : CGFloat = 0.0
    var hashValue: Int {
        return "(\(x),\(y),\(z))".hashValue
    }
    static func == (lhs: Point3D, rhs: Point3D) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z
    }
}
var map : [Point2D : Point3D] = [:]
map.updateValue(Point3D(x: 10.0, y: 20.0,z:0), forKey: Point2D(x: 10.0, 
y: 20.0))
let p = map[Point2D(x: 10.0, y: 20.0)]!
小智 5
如果您不介意效率低下,则可以轻松地将元组转换为字符串,然后将其用作字典键...
var dict = Dictionary<String, SKShapeNode>() 
let tup = (3,4)
let key:String = "\(tup)"
dict[key] = ...
不幸的是,从 Swift 4.2 开始,标准库仍然没有Hashable为元组提供条件一致性,编译器认为这不是有效代码:
extension (T1, T2): Hashable where T1: Hashable, T2: Hashable {
  // potential generic `Hashable` implementation here..
}
此外,将元组作为其字段的结构、类和枚举将不会得到 Hashable自动合成。
虽然其他答案建议使用数组而不是元组,但这会导致效率低下。元组是一种非常简单的结构,由于元素的数量和类型在编译时已知,因此可以轻松优化。一个Array实例几乎总是预先分配更多的连续内存以适应要添加的潜在元素。此外,使用Array类型强制您要么使项目类型相同,要么使用类型擦除。也就是说,如果你不关心低效率(Int, Int)可以存储在[Int],但(String, Int)需要类似的东西[Any].
我发现的解决方法依赖于Hashable为单独存储的字段自动合成这一事实,因此即使没有像Marek Gregor 的回答那样手动添加Hashable和Equatable实现,此代码也能工作:
struct Pair<T: Hashable, U: Hashable>: Hashable {
  let first: T
  let second: U
}
| 归档时间: | 
 | 
| 查看次数: | 13714 次 | 
| 最近记录: |