检查 Julia 数组的所有元素是否相等
Check if all the elements of a Julia array are equal
我能想到的测试数组 arr
中所有元素是否相等的最短方法是 all(arr[1] .== arr)
。虽然这当然很短,但似乎有点不雅。是否有执行此操作的内置函数?
我怀疑有一些类似于 ==(arr...)
的东西,但这不起作用,因为 ==
运算符只能接受两个参数。我不确定 Julia 是如何解析像 arr[1] == arr[2] == arr[3]
这样的表达式的,但是有什么方法可以让它适应具有任意数量元素的数组吗?
all
是正确的解决方案,但您需要谓词 p
和可迭代 itr
的方法 all(p, itr)
,因为它会采用短路行为(中断一旦找到 false
)。所以:
all(y->y==x[1], x)
要查看差异,您可以运行下面的小速度测试:
for n = 100000:250000:1100000
x = rand(1:2, n);
@time all(x .== x[1]);
@time all(y->y==x[1], x);
println("------------------------")
end
忽略第一次迭代,因为它是计时编译时间。
0.000177 seconds (22 allocations: 17.266 KiB)
0.006155 seconds (976 allocations: 55.062 KiB)
------------------------
0.000531 seconds (23 allocations: 47.719 KiB)
0.000003 seconds (1 allocation: 16 bytes)
------------------------
0.000872 seconds (23 allocations: 78.219 KiB)
0.000001 seconds (1 allocation: 16 bytes)
------------------------
0.001210 seconds (23 allocations: 108.781 KiB)
0.000001 seconds (1 allocation: 16 bytes)
------------------------
0.001538 seconds (23 allocations: 139.281 KiB)
0.000002 seconds (1 allocation: 16 bytes)
第一个解决方案显然是 O(n),而第二个解决方案最好是 O(1),最坏是 O(n)(取决于 itr
的数据生成过程)。
@tparker 问得好,@ColinTBowers 回答得好。在尝试同时考虑它们时,我想到了尝试 直接的老派 Julian 方式-for
-loop。结果在相同元素的长向量的重要输入上更快,所以我添加了这个注释。另外,函数名 allequal
似乎可以提一下。所以这是变体:
allequal_1(x) = all(y->y==x[1],x)
# allequal_2(x) used to be erroneously defined as foldl(==,x)
@inline function allequal_3(x)
length(x) < 2 && return true
e1 = x[1]
i = 2
@inbounds for i=2:length(x)
x[i] == e1 || return false
end
return true
end
和基准:
julia> using BenchmarkTools
julia> v = fill(1,10_000_000); # long vector of 1s
julia> allequal_1(v)
true
julia> allequal_3(v)
true
julia> @btime allequal_1($v);
9.573 ms (1 allocation: 16 bytes)
julia> @btime allequal_3($v);
6.853 ms (0 allocations: 0 bytes)
更新:基准测试的另一个重要案例是存在短路机会时。所以(按照评论中的要求):
julia> v[100] = 2
2
julia> allequal_1(v),allequal_2(v),allequal_3(v)
(false, false, false)
julia> @btime allequal_1($v);
108.946 ns (1 allocation: 16 bytes)
julia> @btime allequal_3($v);
68.221 ns (0 allocations: 0 bytes)
在所有条件相同的情况下,for
版本在 Base 中应该是 allequal
。
只是一点点改进:allsame(x) = all(y -> y == first(x), x)
比 allsame(x) = all(y -> y == x[1], x)
更通用,即使 x
不是 AbstractArray
也能正常工作,例如发电机。
我能想到的测试数组 arr
中所有元素是否相等的最短方法是 all(arr[1] .== arr)
。虽然这当然很短,但似乎有点不雅。是否有执行此操作的内置函数?
我怀疑有一些类似于 ==(arr...)
的东西,但这不起作用,因为 ==
运算符只能接受两个参数。我不确定 Julia 是如何解析像 arr[1] == arr[2] == arr[3]
这样的表达式的,但是有什么方法可以让它适应具有任意数量元素的数组吗?
all
是正确的解决方案,但您需要谓词 p
和可迭代 itr
的方法 all(p, itr)
,因为它会采用短路行为(中断一旦找到 false
)。所以:
all(y->y==x[1], x)
要查看差异,您可以运行下面的小速度测试:
for n = 100000:250000:1100000
x = rand(1:2, n);
@time all(x .== x[1]);
@time all(y->y==x[1], x);
println("------------------------")
end
忽略第一次迭代,因为它是计时编译时间。
0.000177 seconds (22 allocations: 17.266 KiB)
0.006155 seconds (976 allocations: 55.062 KiB)
------------------------
0.000531 seconds (23 allocations: 47.719 KiB)
0.000003 seconds (1 allocation: 16 bytes)
------------------------
0.000872 seconds (23 allocations: 78.219 KiB)
0.000001 seconds (1 allocation: 16 bytes)
------------------------
0.001210 seconds (23 allocations: 108.781 KiB)
0.000001 seconds (1 allocation: 16 bytes)
------------------------
0.001538 seconds (23 allocations: 139.281 KiB)
0.000002 seconds (1 allocation: 16 bytes)
第一个解决方案显然是 O(n),而第二个解决方案最好是 O(1),最坏是 O(n)(取决于 itr
的数据生成过程)。
@tparker 问得好,@ColinTBowers 回答得好。在尝试同时考虑它们时,我想到了尝试 直接的老派 Julian 方式-for
-loop。结果在相同元素的长向量的重要输入上更快,所以我添加了这个注释。另外,函数名 allequal
似乎可以提一下。所以这是变体:
allequal_1(x) = all(y->y==x[1],x)
# allequal_2(x) used to be erroneously defined as foldl(==,x)
@inline function allequal_3(x)
length(x) < 2 && return true
e1 = x[1]
i = 2
@inbounds for i=2:length(x)
x[i] == e1 || return false
end
return true
end
和基准:
julia> using BenchmarkTools
julia> v = fill(1,10_000_000); # long vector of 1s
julia> allequal_1(v)
true
julia> allequal_3(v)
true
julia> @btime allequal_1($v);
9.573 ms (1 allocation: 16 bytes)
julia> @btime allequal_3($v);
6.853 ms (0 allocations: 0 bytes)
更新:基准测试的另一个重要案例是存在短路机会时。所以(按照评论中的要求):
julia> v[100] = 2
2
julia> allequal_1(v),allequal_2(v),allequal_3(v)
(false, false, false)
julia> @btime allequal_1($v);
108.946 ns (1 allocation: 16 bytes)
julia> @btime allequal_3($v);
68.221 ns (0 allocations: 0 bytes)
在所有条件相同的情况下,for
版本在 Base 中应该是 allequal
。
只是一点点改进:allsame(x) = all(y -> y == first(x), x)
比 allsame(x) = all(y -> y == x[1], x)
更通用,即使 x
不是 AbstractArray
也能正常工作,例如发电机。