提问人:Alec 提问时间:6/12/2020 更新时间:9/13/2020 访问量:977
与数组的结构相等
Struct equality with arrays
问:
如果我在结构体中有数组,如下所示,我无法比较结构体的相等性,因为数组是可变的?有没有办法让相等性传递到数组,以便我得到 ?还是这样做的唯一方法是扩展?true
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
答:
11赞
Przemyslaw Szufel
6/12/2020
#1
@miguel raz 的答案根本不起作用!
发生这种情况是因为实际上是在调用而不是调用。在文档中,您可以明确地找到:isequal
==
==
isequal
isequal
调用的默认实现,所以不涉及的类型 浮点值一般只需要定义
isequal
==
==
因此,正确的代码是:
struct A
v
end
import Base.==
==(x::A,y::A) = x.v==y.v
但是,一种更优雅的方法是编写一个不依赖于 具有字段的通用代码。由于我们不想重载默认运算符,因此我们可以定义一个类型来告诉 Julia 使用我们的实现:v
==
abstract
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
评论
0赞
dividebyzero
6/22/2020
这很好,尽管看起来您正在像类型类一样使用 Julia 的继承。如果原始结构已经有基类,会发生什么情况?
0赞
Przemyslaw Szufel
6/23/2020
不幸的是,Julia 没有多重继承,因此您需要定义类似function ==(a::T, b::T) where T <: Union{Comparable,SomeOtherType}
3赞
Jay Lieske
9/13/2020
#2
正如@Przemyslaw回答的那样,需要超载。
对于抽象类实现不起作用的情况,重载可以作为单行来完成(避免语句):==
import
Base.:(==)(a::A, b::A) = Base.:(==)(a.v, a.v)
最好还覆盖(对于不需要特殊 NaN 和缺失值语义的结构)和(对于可用作键的结构):isequal
hash
Base.isequal(a::A, b::A) = Base.isequal(a.v, b.v)
Base.hash(a::A, h::UInt) = Base.hash(a.v, h)
评论