diff --git a/base/set.jl b/base/set.jl index 1a25aa1c2a859..6afff54d7cf0a 100644 --- a/base/set.jl +++ b/base/set.jl @@ -178,16 +178,41 @@ function unique(f, C) out end -# If A is not grouped, then we will need to keep track of all of the elements that we have -# seen so far. -function _unique!(A::AbstractVector) - seen = Set{eltype(A)}() +""" + unique!(f, A::AbstractVector) + +Selects one value from `A` for each unique value produced by `f` applied to +elements of `A` , then return the modified A. + +# Examples +```jldoctest +julia> unique!(x -> x^2, [1, -1, 3, -3, 4]) +3-element Array{Int64,1}: + 1 + 3 + 4 + +julia> unique!(n -> n%3, [5, 1, 8, 9, 3, 4, 10, 7, 2, 6]) +3-element Array{Int64,1}: + 5 + 1 + 9 + +julia> unique!(iseven, [2, 3, 5, 7, 9]) +2-element Array{Int64,1}: + 2 + 3 +``` +""" +function unique!(f, A::AbstractVector) + seen = Set() idxs = eachindex(A) y = iterate(idxs) count = 0 for x in A - if x ∉ seen - push!(seen, x) + t = f(x) + if t ∉ seen + push!(seen,t) count += 1 A[y[1]] = x y = iterate(idxs, y[2]) @@ -196,6 +221,10 @@ function _unique!(A::AbstractVector) resize!(A, count) end +# If A is not grouped, then we will need to keep track of all of the elements that we have +# seen so far. +_unique!(A::AbstractVector) = unique!(identity, A::AbstractVector) + # If A is grouped, so that each unique element is in a contiguous group, then we only # need to keep track of one element at a time. We replace the elements of A with the # unique elements that we see in the order that we see them. Once we have iterated diff --git a/test/sets.jl b/test/sets.jl index e9342439f0a2f..ebe9db8ba90d9 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -398,6 +398,10 @@ end unique!(u) @test u == [5,"w","we","r"] u = [1,2,5,1,3,2] + @test unique!(x -> x ^ 2, [1, -1, 3, -3, 5, -5]) == [1, 3, 5] + @test unique!(n -> n % 3, [5, 1, 8, 9, 3, 4, 10, 7, 2, 6]) == [5, 1, 9] + @test unique!(iseven, [2, 3, 5, 7, 9]) == [2, 3] + @test unique!(x -> x % 2 == 0 ? :even : :odd, [1, 2, 3, 4, 2, 2, 1]) == [1, 2] end @testset "allunique" begin