diff --git a/NEWS.md b/NEWS.md index 053ed9e711ecb..d182f079dfd1f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,7 @@ New language features to enforce the involved function calls to be (or not to be) inlined. ([#41312]) * The default behavior of observing `@inbounds` declarations is now an option via `auto` in `--check-bounds=yes|no|auto` ([#41551]) * New function `eachsplit(str)` for iteratively performing `split(str)`. +* New function `allequal(itr)` for testing if all elements in an iterator are equal. ([#43354]) * `∀`, `∃`, and `∄` are now allowed as identifier characters ([#42314]). * Support for Unicode 14.0.0 ([#43443]). * `try`-blocks can now optionally have an `else`-block which is executed right after the main body only if diff --git a/base/exports.jl b/base/exports.jl index c43e66eecb74c..2d790f16b7986 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -497,6 +497,7 @@ export # collections all!, all, + allequal, allunique, any!, any, diff --git a/base/set.jl b/base/set.jl index dd1400d11dba1..371799f2e3ff5 100644 --- a/base/set.jl +++ b/base/set.jl @@ -115,7 +115,7 @@ as determined by [`isequal`](@ref), in the order that the first of each set of equivalent elements originally appears. The element type of the input is preserved. -See also: [`unique!`](@ref), [`allunique`](@ref). +See also: [`unique!`](@ref), [`allunique`](@ref), [`allequal`](@ref). # Examples ```jldoctest @@ -383,7 +383,7 @@ end Return `true` if all values from `itr` are distinct when compared with [`isequal`](@ref). -See also: [`unique`](@ref), [`issorted`](@ref). +See also: [`unique`](@ref), [`issorted`](@ref), [`allequal`](@ref). # Examples ```jldoctest @@ -427,6 +427,40 @@ allunique(::Union{AbstractSet,AbstractDict}) = true allunique(r::AbstractRange) = !iszero(step(r)) || length(r) <= 1 +""" + allequal(itr) -> Bool + +Return `true` if all values from `itr` are equal when compared with [`isequal`](@ref). + +See also: [`unique`](@ref), [`allunique`](@ref). + +!!! compat "Julia 1.8" + The `allequal` function requires at least Julia 1.8. + +# Examples +```jldoctest +julia> allequal([]) +true + +julia> allequal([1]) +true + +julia> allequal([1, 1]) +true + +julia> allequal([1, 2]) +false + +julia> allequal(Dict(:a => 1, :b => 1)) +false +``` +""" +allequal(itr) = isempty(itr) ? true : all(isequal(first(itr)), itr) + +allequal(c::Union{AbstractSet,AbstractDict}) = length(c) <= 1 + +allequal(r::AbstractRange) = iszero(step(r)) || length(r) <= 1 + filter!(f, s::Set) = unsafe_filter!(f, s) const hashs_seed = UInt === UInt64 ? 0x852ada37cfe8e0ce : 0xcfe8e0ce diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 221adad3954e6..511ab786e158c 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -94,6 +94,7 @@ Base.indexin Base.unique Base.unique! Base.allunique +Base.allequal Base.reduce(::Any, ::Any) Base.foldl(::Any, ::Any) Base.foldr(::Any, ::Any) diff --git a/test/sets.jl b/test/sets.jl index da5800f6166a7..43ba433e780d7 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -511,6 +511,35 @@ end @test allunique(r) == invoke(allunique, Tuple{Any}, r) end end + +@testset "allequal" begin + @test allequal(Set()) + @test allequal(Set(1)) + @test !allequal(Set([1, 2])) + @test allequal(Dict()) + @test allequal(Dict(:a => 1)) + @test !allequal(Dict(:a => 1, :b => 2)) + @test allequal([]) + @test allequal([1]) + @test allequal([1, 1]) + @test !allequal([1, 1, 2]) + @test allequal([:a, :a]) + @test !allequal([:a, :b]) + @test !allequal(1:2) + @test allequal(1:1) + @test !allequal(4.0:0.3:7.0) + @test allequal(4:-1:5) # empty range + @test !allequal(7:-1:1) # negative step + @test !allequal(Date(2018, 8, 7):Day(1):Date(2018, 8, 11)) # JuliaCon 2018 + @test !allequal(DateTime(2018, 8, 7):Hour(1):DateTime(2018, 8, 11)) + @test allequal(StepRangeLen(1.0, 0.0, 2)) + @test !allequal(StepRangeLen(1.0, 1.0, 2)) + @test allequal(LinRange(1, 1, 0)) + @test allequal(LinRange(1, 1, 1)) + @test allequal(LinRange(1, 1, 2)) + @test !allequal(LinRange(1, 2, 2)) +end + @testset "filter(f, ::$S)" for S = (Set, BitSet) s = S([1,2,3,4]) @test s !== filter( isodd, s) == S([1,3])