使简单元组符合Hashable,因此可以是Dictionary Key

时间:2016-12-21 00:20:24

标签: swift dictionary protocols hashable

我想使用一个非常简单的元组作为关键字:

Double x = 3.74 * Math.Pow(10.0, -2);
Double y = -0.825;
Double z = 0.16 * Math.Pow(10.0, 2);
Double v;

v = 1 + Math.Pow(Math.Sin, 2)(x + y) / Math.Abs(x - 2*y/1 + Math.Pow(x, 2) + Math.Pow(y, 2)) * Math.Pow(x, Math.Abs(y)) + Math.Pow(Math.Cos, 2)*(Math.Atan * 1/z);

Console.WriteLine(v);

Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);

字典键需要是Hashable。我已经学会了。

但无法找到我如何使这个简单的元组Hashable,并且在最好的时候确实很难与协议一致。

更深刻的是,CGPoint可以解决我的问题。它可以是这种格式,但不可清除。

是否有可能扩展CGPoint以便它可以播放?如果是这样,怎么样?

编辑:CGPoint选择的Int变体的图像。

enter image description here

1 个答案:

答案 0 :(得分:6)

使用Hashable对于类,结构或枚举并不困难。 您只需要明确声明与Hashable的一致性并定义属性hashValue: Int。实际上,hashValue需要实现一个简单的公理: 如果a == b则a.hashValue == b.hashValue

(为了符合Hashable,您还需要输入Equatable类型。如果是CGPoint,则它已经是Equatable。)

使CGPoint符合Hashable的示例:

extension CGPoint: Hashable {
    public var hashValue: Int {
        //This expression can be any of the arbitrary expression which fulfills the axiom above.
        return x.hashValue ^ y.hashValue
    }
}

var pointDict: [CGPoint: String] = [
    CGPoint(x: 1.0, y: 2.0): "PointA",
    CGPoint(x: 3.0, y: 4.0): "PointB",
    CGPoint(x: 5.0, y: 6.0): "PointC",
]
print(pointDict[CGPoint(x: 1.0, y: 2.0)]) //->Optional("PointA")

由于CGPoint包含CGFloat值,因此,CGPoint作为字典键可能会导致基于二进制浮点系统的计算错误的意外行为。你需要格外小心使用它。

<强> ADDITION

如果您想避免某些计算错误问题并且可以接受该结构只能包含Int,您可以定义自己的结构并使其符合Hashable

struct MyPoint {
    var x: Int
    var y: Int
}
extension MyPoint: Hashable {
    public var hashValue: Int {
        return x.hashValue ^ y.hashValue
    }

    public static func == (lhs: MyPoint, rhs: MyPoint) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }
}
var myPointDict: [MyPoint: String] = [
    MyPoint(x: 1, y: 2): "MyPointA",
    MyPoint(x: 3, y: 4): "MyPointB",
    MyPoint(x: 5, y: 6): "MyPointC",
]
print(myPointDict[MyPoint(x: 1, y: 2)]) //->Optional("MyPointA")

比上面的代码困难得多,你需要的另一件事就是为结构定义==运算符。请试一试。