配列arr
のすべての要素が等しいかどうかをテストするために考えられる最も短い方法は、all(arr[1] .== arr)
です。これは確かに短いですが、少しエレガントではないようです。これを行う組み込み関数はありますか?
==(arr...)
に沿って何かがあるのではないかと思いますが、==
演算子は2つの引数しか取れないため、機能しません。 Juliaがarr[1] == arr[2] == arr[3]
のような式をどのように解析するかはわかりませんが、これを任意の数の要素を持つ配列に適応させる方法はありますか?
素晴らしい質問@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
になるはずです。
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
のデータ生成プロセス)。
ほんの少し改良:allsame(x) = all(y -> y == first(x), x)
はallsame(x) = all(y -> y == x[1], x)
よりも一般的で、x
がAbstractArray
以外の場合でも機能します。ジェネレータ。