与数组的结构相等
Struct equality with arrays
如果我在结构中有数组,如下所示,我无法比较结构的相等性,因为数组是可变的?有没有办法让相等性传递给数组,以便我得到 true
for a([1,2,3]) == a([1,2,3])
?或者这是扩展 Base.==
的唯一方法吗?
julia> struct a
v
end
julia> a([1,2,3]) == a([1,2,3])
false
julia> a(1) == a(1)
true
julia> [1,2,3] == [1,2,3] # want the equality to work like this for the struct
true
julia> [1,2,3] === [1,2,3]
false
@miguel raz 的回答根本不起作用!
发生这种情况是因为 isequal
实际上是在调用 ==
而不是 ==
调用 isequal
。在 isequal
文档中,您可以明确地发现:
The default implementation of isequal
calls ==
, so a type that does not involve
floating-point values generally only needs to define ==
因此正确的代码是:
struct A
v
end
import Base.==
==(x::A,y::A) = x.v==y.v
但是,更优雅的方法是编写不依赖于字段 v
的通用代码。由于我们不想重载默认的 ==
运算符,我们可以定义一个 abstract
类型来告诉 Julia 使用我们的实现:
abstract type Comparable end
import Base.==
function ==(a::T, b::T) where T <: Comparable
f = fieldnames(T)
getfield.(Ref(a),f) == getfield.(Ref(b),f)
end
现在您可以定义自己的结构来正确比较:
struct B <: Comparable
x
y
end
测试:
julia> b1 = B([1,2],[B(7,[1])]);
julia> b2 = B([1,2],[B(7,[1])])
julia> b1 == b2
true
正如@Przemyslaw 回答的那样,需要 ==
的重载。
对于抽象 class 实现不起作用的情况,重载可以作为 one-liner 完成(避免 import
语句):
Base.:(==)(a::A, b::A) = Base.:(==)(a.v, a.v)
最好也覆盖 isequal
(对于不需要特殊 NaN 和缺失值语义的结构)和 hash
(对于可用作键的结构):
Base.isequal(a::A, b::A) = Base.isequal(a.v, b.v)
Base.hash(a::A, h::UInt) = Base.hash(a.v, h)
如果我在结构中有数组,如下所示,我无法比较结构的相等性,因为数组是可变的?有没有办法让相等性传递给数组,以便我得到 true
for a([1,2,3]) == a([1,2,3])
?或者这是扩展 Base.==
的唯一方法吗?
julia> struct a
v
end
julia> a([1,2,3]) == a([1,2,3])
false
julia> a(1) == a(1)
true
julia> [1,2,3] == [1,2,3] # want the equality to work like this for the struct
true
julia> [1,2,3] === [1,2,3]
false
@miguel raz 的回答根本不起作用!
发生这种情况是因为 isequal
实际上是在调用 ==
而不是 ==
调用 isequal
。在 isequal
文档中,您可以明确地发现:
The default implementation of
isequal
calls==
, so a type that does not involve floating-point values generally only needs to define==
因此正确的代码是:
struct A
v
end
import Base.==
==(x::A,y::A) = x.v==y.v
但是,更优雅的方法是编写不依赖于字段 v
的通用代码。由于我们不想重载默认的 ==
运算符,我们可以定义一个 abstract
类型来告诉 Julia 使用我们的实现:
abstract type Comparable end
import Base.==
function ==(a::T, b::T) where T <: Comparable
f = fieldnames(T)
getfield.(Ref(a),f) == getfield.(Ref(b),f)
end
现在您可以定义自己的结构来正确比较:
struct B <: Comparable
x
y
end
测试:
julia> b1 = B([1,2],[B(7,[1])]);
julia> b2 = B([1,2],[B(7,[1])])
julia> b1 == b2
true
正如@Przemyslaw 回答的那样,需要 ==
的重载。
对于抽象 class 实现不起作用的情况,重载可以作为 one-liner 完成(避免 import
语句):
Base.:(==)(a::A, b::A) = Base.:(==)(a.v, a.v)
最好也覆盖 isequal
(对于不需要特殊 NaN 和缺失值语义的结构)和 hash
(对于可用作键的结构):
Base.isequal(a::A, b::A) = Base.isequal(a.v, b.v)
Base.hash(a::A, h::UInt) = Base.hash(a.v, h)