Julia含向量的复合类型对象相等性测试不符合预期,如何正确比较?
现象原因
- Julia 中自定义不可变结构体(
struct定义的非可变类型)的默认相等比较逻辑:- 默认的
==运算符会回退调用===(恒等比较),isequal默认也和===行为对齐,除非用户手动重载。 - 对于字段全是*位类型(bitstype)*的结构体(比如你第一个例子里的
mytype,字段是Int64属于位类型),===会直接比较结构体存储的二进制内容,两个实例字段值相同时就会返回true。 - 当结构体包含
Vector这类引用类型(可变、内存地址独立的类型)时,===比较的是对象的内存身份标识:你代码里的两个[5]是独立创建的两个向量对象,内存地址不同,所以===返回false,进而默认的==、isequal都返回false。
- 默认的
注:向量本身的
==已经实现了逐元素比较逻辑,[5] == [5]本身返回true,只是默认的结构体比较没有调用字段自身的==逻辑,直接用了恒等比较。
正确比较的实现方法
最通用的方案是手动为你的自定义结构体重载Base.:(==)、Base.isequal和Base.hash方法,按照你需要的相等逻辑实现:
struct mytype2 stuff::Vector{Int64} end # 重载相等比较逻辑:两个实例的stuff字段相等则判定为相等 Base.:(==)(x::mytype2, y::mytype2) = x.stuff == y.stuff # 配套重载isequal,保证和==行为一致 Base.isequal(x::mytype2, y::mytype2) = isequal(x.stuff, y.stuff) # 配套重载hash,保证相等的实例哈希值相同,避免在Dict、Set等容器中出现异常 Base.hash(x::mytype2, h::UInt) = hash(x.stuff, h)
重载后再测试就会符合预期:
a = mytype2([5]) b = mytype2([5]) a == b # 返回 true isequal(a, b) # 返回 true
如果你的结构体中的向量不需要修改,也可以选择静态不可变数组类型(所有元素都是位类型的静态数组本身也属于位类型),不需要重载也能默认按值比较。
内容的提问来源于stack exchange,提问作者Vance
相关产品推荐
相关产品推荐

