Skip to content

Commit 84057ee

Browse files
authored
Merge pull request #19943 from stevengj/fastpush
improvements to push!, unshift!, append!, prepend!
2 parents 23b04b8 + 01be289 commit 84057ee

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

base/array.jl

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,15 +554,17 @@ function push!(a::Array{Any,1}, item::ANY)
554554
end
555555

556556
function append!{T}(a::Array{T,1}, items::AbstractVector)
557-
n = length(items)
557+
itemindices = eachindex(items)
558+
n = length(itemindices)
558559
ccall(:jl_array_grow_end, Void, (Any, UInt), a, n)
559-
copy!(a, length(a)-n+1, items, 1, n)
560+
copy!(a, length(a)-n+1, items, first(itemindices), n)
560561
return a
561562
end
562563

563564
append!(a::Vector, iter) = _append!(a, iteratorsize(iter), iter)
565+
push!(a::Vector, iter...) = append!(a, iter)
564566

565-
function _append!(a, ::HasLength, iter)
567+
function _append!(a, ::Union{HasLength,HasShape}, iter)
566568
n = length(a)
567569
resize!(a, n+length(iter))
568570
@inbounds for (i,item) in zip(n+1:length(a), iter)
@@ -591,17 +593,42 @@ julia> prepend!([3],[1,2])
591593
3
592594
```
593595
"""
596+
function prepend! end
597+
594598
function prepend!{T}(a::Array{T,1}, items::AbstractVector)
595-
n = length(items)
599+
itemindices = eachindex(items)
600+
n = length(itemindices)
596601
ccall(:jl_array_grow_beg, Void, (Any, UInt), a, n)
597602
if a === items
598603
copy!(a, 1, items, n+1, n)
599604
else
600-
copy!(a, 1, items, 1, n)
605+
copy!(a, 1, items, first(itemindices), n)
601606
end
602607
return a
603608
end
604609

610+
prepend!(a::Vector, iter) = _prepend!(a, iteratorsize(iter), iter)
611+
unshift!(a::Vector, iter...) = prepend!(a, iter)
612+
613+
function _prepend!(a, ::Union{HasLength,HasShape}, iter)
614+
n = length(iter)
615+
ccall(:jl_array_grow_beg, Void, (Any, UInt), a, n)
616+
i = 0
617+
for item in iter
618+
@inbounds a[i += 1] = item
619+
end
620+
a
621+
end
622+
function _prepend!(a, ::IteratorSize, iter)
623+
n = 0
624+
for item in iter
625+
n += 1
626+
unshift!(a, item)
627+
end
628+
reverse!(a, 1, n)
629+
a
630+
end
631+
605632

606633
"""
607634
resize!(a::Vector, n::Integer) -> Vector

test/arrayops.jl

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,10 +1122,31 @@ A = [[i i; i i] for i=1:2]
11221122
@test cumsum(A) == Any[[1 1; 1 1], [3 3; 3 3]]
11231123
@test cumprod(A) == Any[[1 1; 1 1], [4 4; 4 4]]
11241124

1125-
# PR #4627
1126-
A = [1,2]
1127-
@test append!(A, A) == [1,2,1,2]
1128-
@test prepend!(A, A) == [1,2,1,2,1,2,1,2]
1125+
isdefined(Main, :TestHelpers) || eval(Main, :(include("TestHelpers.jl")))
1126+
using TestHelpers.OAs
1127+
1128+
@testset "prepend/append" begin
1129+
# PR #4627
1130+
A = [1,2]
1131+
@test append!(A, A) == [1,2,1,2]
1132+
@test prepend!(A, A) == [1,2,1,2,1,2,1,2]
1133+
1134+
# iterators with length:
1135+
@test append!([1,2], (9,8)) == [1,2,9,8] == push!([1,2], (9,8)...)
1136+
@test prepend!([1,2], (9,8)) == [9,8,1,2] == unshift!([1,2], (9,8)...)
1137+
@test append!([1,2], ()) == [1,2] == prepend!([1,2], ())
1138+
# iterators without length:
1139+
g = (i for i = 1:10 if iseven(i))
1140+
@test append!([1,2], g) == [1,2,2,4,6,8,10] == push!([1,2], g...)
1141+
@test prepend!([1,2], g) == [2,4,6,8,10,1,2] == unshift!([1,2], g...)
1142+
g = (i for i = 1:2:10 if iseven(i)) # isempty(g) == true
1143+
@test append!([1,2], g) == [1,2] == push!([1,2], g...)
1144+
@test prepend!([1,2], g) == [1,2] == unshift!([1,2], g...)
1145+
1146+
# offset array
1147+
@test append!([1,2], OffsetArray([9,8], (-3,))) == [1,2,9,8]
1148+
@test prepend!([1,2], OffsetArray([9,8], (-3,))) == [9,8,1,2]
1149+
end
11291150

11301151
A = [1,2]
11311152
s = Set([1,2,3])
@@ -1880,9 +1901,6 @@ end
18801901
end
18811902
end
18821903

1883-
isdefined(Main, :TestHelpers) || eval(Main, :(include("TestHelpers.jl")))
1884-
using TestHelpers.OAs
1885-
18861904
@testset "accumulate, accumulate!" begin
18871905

18881906
@test accumulate(+, [1,2,3]) == [1, 3, 6]

0 commit comments

Comments
 (0)