如何使用自定义类类型作为Swift中Dictionary的键?

时间:2015-07-10 04:50:54

标签: swift dictionary

我正在开发一个使用Swift构建的项目,我正在尝试创建一个字典来存储一个名为Pixel的自定义类的对象(KEY,用于存储RGB值等颜色信息)和int值(Value,for计算出现在同一图像上的相同颜色的次数)。

如果这是在C#中,则工作代码应为:

Dictionary<Pixel, int> colorDictionary = new Dictionary< Pixel, int> ();

在Swift中,我尝试过:

var colorDictionary = Dictionary<Pixel, Int>()

然而,我得到的错误:

  

“类型'Pixel'不符合协议'Hashable'”

我该怎么做才能解决这个问题?非常感谢!

4 个答案:

答案 0 :(得分:4)

您要使用字典键的任何自定义类型都必须符合Hashable协议。

此协议有一个必须实现的属性。

var hashValue: Int { get }

使用此属性生成一个int,Dictionary可以将其用于查找原因。您应该尝试使其生成的hashValue对于每个像素都是唯一的。

Swift书中有以下注释,因此您可以随机创建哈希(只要它是唯一的):

  

类型的hashValue属性返回的值在同一程序的不同执行或不同程序中不需要相同。

请注意,由于Hashable继承自Equatable,您还必须实施:

func ==(_ lhs: Self, _ rhs: Self) -> Bool.

我不确定像素的内部结构是什么,但是当两者具有相同的“x”和“y”值时,你可能会认为两个像素相等。最后的逻辑取决于你。

根据需要修改:

struct Pixel : Hashable {

    // MARK: Hashable
    var hashValue: Int {
        get {
            // Do some operations to generate a unique hash.
        }
    }
}

//MARK: Equatable
func ==(lh: Pixel, rh: Pixel) -> Bool {
    return lh.x == rh.x && rh.y == lh.y
}

答案 1 :(得分:3)

继续Andy Ibanez发布的内容。实现hashValue的快捷方式是捎带String的hashValue。你可以这样做。

class Pixel: Hashable {
    var r:Int = 0;
    var g:Int = 0;
    var b:Int = 0;
    var a:Int = 0;

    var hashValue: Int {
        get {
            return "\(r)\(g)\(b)\(a)".hashValue;
        }
    }
}

你还需要一个Equatable函数,因为在这种情况下hashValues只是一个快速检查,用于验证两个对象是不相等的。由于两个对象可能具有相同的hashValue但不相等,因此您仍需要实现==以定义如下所示的相等性。

func ==(lhs: Pixel, rhs: Pixel) -> Bool{
    if lhs.r != rhs.r{
        return false;
    }
    if lhs.g != rhs.g{
        return false;
    }
    if lhs.b != rhs.b{
        return false;
    }
    if lhs.a != rhs.a{
        return false;
    }
    return true;
}

答案 2 :(得分:1)

实现Hashable协议,如下所示:

class Pixel : Hashable {
    var alpha, red, green, blue : Int

    init(red: Int, green: Int, blue: Int, alpha: Int) {
        self.red = red
        self.green = green
        self.blue = blue
        self.alpha = alpha
    }

    var hashValue : Int {
        get {
            return alpha ^ red ^ green ^ blue
        }
    }
}

func ==(lhs: Pixel, rhs: Pixel) -> Bool {
    return lhs.alpha == rhs.alpha && lhs.red == rhs.red && lhs.green == rhs.green && lhs.blue == rhs.blue
}

答案 3 :(得分:0)

从不推荐使用的Swift 4.2 hashValue 中删除。

现在,如果要自定义类型实现 Hashable 的方式,则可以覆盖 hash(into:)方法,而不是hashValue。 hash(into:)方法通过引用传递一个Hasher对象,您将其称为 combine(_:)以添加您类型的基本状态信息。

class Pixel {
    var alpha, red, green, blue : Int
}

//MARK : Hashable implementation
    extension Pixel : Hashable {
    func hash(into hasher: inout Hasher) {
            hasher.combine(self.red)
            hasher.combine(self.green)
            hasher.combine(self.blue)
            hasher.combine(self.alpha)

        }
    }