web-dev-qa-db-ja.com

Julia配列のすべての要素が等しいかどうかを確認します

配列arrのすべての要素が等しいかどうかをテストするために考えられる最も短い方法は、all(arr[1] .== arr)です。これは確かに短いですが、少しエレガントではないようです。これを行う組み込み関数はありますか?

==(arr...)に沿って何かがあるのではないかと思いますが、==演算子は2つの引数しか取れないため、機能しません。 Juliaがarr[1] == arr[2] == arr[3]のような式をどのように解析するかはわかりませんが、これを任意の数の要素を持つ配列に適​​応させる方法はありますか?

16
tparker

素晴らしい質問@tparkerと素晴らしい答え@ColinTBowers。それらの両方について考えようとしているときに、ストレートフォワードオールドスクールジュリアンの方法-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)

更新:ベンチマークのもう1つの重要なケースは、短絡の機会がある場合です。したがって(コメントで要求されたとおり):

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になるはずです。

12
Dan Getz

allは正しい解決策ですが、述語pと反復可能なitrにはメソッドall(p, itr)が必要です。これは、短絡動作(break 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)ですが、2番目の解決策はO(1)せいぜい、最悪の場合O(n) itrのデータ生成プロセス)。

12
Colin T Bowers

ほんの少し改良:allsame(x) = all(y -> y == first(x), x)allsame(x) = all(y -> y == x[1], x)よりも一般的で、xAbstractArray以外の場合でも機能します。ジェネレータ。

9
Pablo San-Jose