Check if all elements of the Julia array are equal

The shortest way I can check if all the elements in the arr array are equal to all(arr[1] .== arr) . Although this, of course, is short, it seems a little inelegant. Is there a built-in function that does this?

I suspect there is something in the lines of ==(arr...) , but this does not work, because the == operator can only take two arguments. I'm not sure how Julia parses expressions like arr[1] == arr[2] == arr[3] , but is there any way to adapt this to an array with an arbitrary number of elements?

+13
equality arrays julia-lang julia
source share
4 answers

Great question @tparker and great answer @ColinTBowers. Trying to think about both of them, it occurred to me to try the straightforward old school of the Julian Way-the-the-t20. The result was faster on the important input of a long vector of identical elements, so I am adding this note. Also, the name of the allequal function seems appropriate enough to mention. So here are the options:

 allequal_1(x) = all(y->y==x[1],x) allequal_2(x) = foldl(==,x) # another way but doesn't short-circuit :( @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 

And the standard:

 julia> using BenchmarkTools julia> v = fill(1,10_000_000); # long vector of 1s julia> allequal_1(v) true julia> allequal_2(v) true julia> allequal_3(v) true julia> @btime allequal_1($v); 9.573 ms (1 allocation: 16 bytes) julia> @btime allequal_2($v); 10.585 ms (0 allocations: 0 bytes) julia> @btime allequal_3($v); 6.853 ms (0 allocations: 0 bytes) 

UPDATE: Another important point for testing is when there is the possibility of a short circuit. Thus (on request in commment):

 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_2($v); 10.325 ms (0 allocations: 0 bytes) julia> @btime allequal_3($v); 68.221 ns (0 allocations: 0 bytes) 

The second version of allequal_2 does not work well, since it does not close.

All things being equal, the for version must be allequal in the database.

+11
source share

all is the correct solution, but you want to use the all(p, itr) for the predicate p and iterable itr , since it will use a short circuit (break, as soon as false is found), So:

 all(y->y==x[1], x) 

To see the difference, you can run the following small speed test:

 for n = 100000:250000:1100000 x = rand(1:2, n); @time all(x .== x[1]); @time all(y->y==x[1], x); println("------------------------") end 

Ignore the first iteration, as this is compilation time.

  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) 

The first solution is pretty obvious O (n), and the second is O (1) at best and O (n) at worst (depending on the data generation process for itr ).

+11
source share

Just a slight improvement: allsame(x) = all(y → y == first(x), x) is more general than allsame(x) = all(y → y == x[1], x) , and it works , even if x is something other than AbstractArray , for example, a generator.

+7
source share

My reputation is not high enough to comment on the answer suggested by foldl(==, x) , but I don't think it works:

 julia> foldl(==, [3,3,3]) false julia> (3 == 3) == 3 false julia> 3 == 3 == 3 true julia> foldl(==, [3,3,1]) true 

In the above example, foldl(==, [3,3,3]) is essentially (3 == 3) == 3 , which simplifies to true == 3 .

0
source share

All Articles