From 322e9aa51bcb2903529c1e705cc6c914fd62b4d5 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 22 Apr 2021 17:50:21 +0200 Subject: [PATCH] NEWS, tests and some fixes --- NEWS.md | 2 ++ base/abstractarray.jl | 8 ++++---- test/abstractarray.jl | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 24be1feb2108d..ad79b2b67c0d1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -39,6 +39,8 @@ New library functions * Two argument methods `findmax(f, domain)`, `argmax(f, domain)` and the corresponding `min` versions ([#27613]). * `isunordered(x)` returns true if `x` is value that is normally unordered, such as `NaN` or `missing`. +* New `keepat!(vector, inds)` function which is the inplace equivalent of `vector[inds]` + for a list `inds` of integers ([#36229]). * New macro `Base.@invokelatest f(args...; kwargs...)` provides a convenient way to call `Base.invokelatest(f, args...; kwargs...)` ([#37971]) * New macro `Base.@invoke f(arg1::T1, arg2::T2; kwargs...)` provides an easier syntax to call `invoke(f, Tuple{T1,T2}; kwargs...)` ([#38438]) * Two arguments method `lock(f, lck)` now accepts a `Channel` as the second argument. ([#39312]) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index dc5b828ff1140..192f9212dc809 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2560,7 +2560,7 @@ Remove the items at all the indices which are not given by `inds`, and return the modified `a`. Items which are kept are shifted to fill the resulting gaps. -`inds` can be either an iterator or a collection of sorted integer indices. +`inds` must be an iterator of sorted and unique integer indices. See also [`deleteat!`](@ref). !!! compat "Julia 1.7" @@ -2576,13 +2576,13 @@ julia> keepat!([6, 5, 4, 3, 2, 1], 1:2:5) ``` """ function keepat!(a::AbstractVector, inds) - isempty(inds) && return a local prev i = firstindex(a) for k in inds - @isdefined(prev) && (prev <= k || throw(ArgumentError("indices must be sorted"))) + @isdefined(prev) && (prev < k || throw(ArgumentError("indices must be sorted"))) + ak = a[k] # must happen even when i==k for bounds checking if i != k - a[i] = a[k] + @inbounds a[i] = ak # k > i, so a[i] is inbounds end prev = k i = nextind(a, i) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index b75869f3ed9d6..28224ad21c045 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1298,3 +1298,24 @@ end @test @inferred(reduce(vcat, x_vecs)) == [5.0, 1.0, 2.0, 3.0] @test @inferred(reduce(vcat, ([10.0], [20.0], Bool[]))) == [10.0, 20.0] end + +@testset "keepat!" begin + a = [1:6;] + @test a === keepat!(a, 1:5) + @test a == 1:5 + @test keepat!(a, [2, 4]) == [2, 4] + @test isempty(keepat!(a, [])) + + a = [1:6;] + @test_throws BoundsError keepat!(a, 1:10) # make sure this is not a no-op + @test_throws BoundsError keepat!(a, 2:10) + @test_throws ArgumentError keepat!(a, [2, 4, 3]) + + b = BitVector([1, 1, 1, 0, 0]) + @test b === keepat!(b, 1:5) + @test b == [1, 1, 1, 0, 0] + @test keepat!(b, 2:4) == [1, 1, 0] + @test_throws BoundsError keepat!(a, -1:10) + @test_throws ArgumentError keepat!(a, [2, 1]) + @test isempty(keepat!(a, [])) +end