Skip to content

Commit df61cfe

Browse files
committed
Implement generic append! method for AbstractArray source
1 parent 89104c6 commit df61cfe

File tree

2 files changed

+128
-68
lines changed

2 files changed

+128
-68
lines changed

src/array.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -699,9 +699,16 @@ function Base.append!(A::CategoricalVector, B::CatArrOrSub)
699699
len = length(A)
700700
len2 = length(B)
701701
resize!(A.refs, len + len2)
702-
for i = 1:len2
703-
A[len + i] = B[i]
704-
end
702+
copyto!(A, len+1, B, 1, len2)
703+
return A
704+
end
705+
706+
function Base.append!(A::CategoricalVector, items::AbstractArray)
707+
itemindices = eachindex(items)
708+
len = length(A)
709+
len2 = length(itemindices)
710+
resize!(A, len+len2)
711+
copyto!(A, len+1, items, first(itemindices), len2)
705712
return A
706713
end
707714

test/13_arraycommon.jl

Lines changed: 118 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -985,56 +985,87 @@ end
985985
a = ["a", "b", "c"]
986986
x = CategoricalVector{String}(a, ordered=ordered)
987987

988-
append!(x, x)
989-
@test length(x) == 6
990-
@test x == ["a", "b", "c", "a", "b", "c"]
991-
@test isordered(x) === ordered
992-
@test levels(x) == ["a", "b", "c"]
988+
x2 = copy(x)
989+
append!(x2, a)
990+
@test x2 == ["a", "b", "c", "a", "b", "c"]
991+
@test isordered(x2) === ordered
992+
@test levels(x2) == ["a", "b", "c"]
993+
994+
x2 = copy(x)
995+
append!(x2, x)
996+
@test x2 == ["a", "b", "c", "a", "b", "c"]
997+
@test isordered(x2) === ordered
998+
@test levels(x2) == ["a", "b", "c"]
993999

9941000
b = ["z","y","x"]
1001+
x2 = copy(x)
1002+
if ordered
1003+
@test_throws OrderedLevelsException append!(x2, b)
1004+
else
1005+
append!(x2, b)
1006+
@test isordered(x2) === false
1007+
@test x2 == ["a", "b", "c", "z", "y", "x"]
1008+
@test levels(x2) == ["a", "b", "c", "z", "y", "x"]
1009+
end
1010+
9951011
y = CategoricalVector{String}(b)
996-
append!(x, y)
997-
@test isordered(x) === ordered
998-
@test length(x) == 9
999-
@test x == ["a", "b", "c", "a", "b", "c", "z", "y", "x"]
1000-
@test levels(x) == ["a", "b", "c", "x", "y", "z"]
1012+
x2 = copy(x)
1013+
append!(x2, y)
1014+
@test isordered(x2) === ordered
1015+
@test x2 == ["a", "b", "c", "z", "y", "x"]
1016+
@test levels(x2) == ["a", "b", "c", "x", "y", "z"]
10011017

10021018
z1 = view(CategoricalVector{String}(["ex1", "ex2"]), 1)
10031019
z2 = view(CategoricalVector{String}(["ex3", "ex4"]), 1:1)
1004-
append!(x, z1)
1005-
append!(x, z2)
1006-
@test isordered(x) === ordered
1007-
@test length(x) == 11
1008-
@test x == ["a", "b", "c", "a", "b", "c", "z", "y", "x", "ex1", "ex3"]
1009-
@test levels(x) == ["a", "b", "c", "x", "y", "z", "ex1", "ex2", "ex3", "ex4"]
1020+
x2 = copy(x)
1021+
append!(x2, z1)
1022+
append!(x2, z2)
1023+
@test isordered(x2) === ordered
1024+
@test x2 == ["a", "b", "c", "ex1", "ex3"]
1025+
@test levels(x2) == ["a", "b", "c", "ex1", "ex2", "ex3", "ex4"]
10101026
end
10111027

10121028
@testset "append! Float64" begin
10131029
a = [-1.0, 0.0, 1.0]
10141030
x = CategoricalVector{Float64}(a, ordered=ordered)
10151031

1016-
append!(x, x)
1017-
@test length(x) == 6
1018-
@test x == [-1.0, 0.0, 1.0, -1.0, 0.0, 1.0]
1019-
@test isordered(x) === ordered
1020-
@test levels(x) == [-1.0, 0.0, 1.0]
1032+
x2 = copy(x)
1033+
append!(x2, a)
1034+
@test x2 == [-1.0, 0.0, 1.0, -1.0, 0.0, 1.0]
1035+
@test isordered(x2) === ordered
1036+
@test levels(x2) == [-1.0, 0.0, 1.0]
1037+
1038+
x2 = copy(x)
1039+
append!(x2, x2)
1040+
@test x2 == [-1.0, 0.0, 1.0, -1.0, 0.0, 1.0]
1041+
@test isordered(x2) === ordered
1042+
@test levels(x2) == [-1.0, 0.0, 1.0]
10211043

10221044
b = [2.5, 3.0, 3.5]
1045+
x2 = copy(x)
1046+
if ordered
1047+
@test_throws OrderedLevelsException append!(x2, b)
1048+
else
1049+
append!(x2, b)
1050+
@test x2 == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5]
1051+
@test isordered(x2) === false
1052+
@test levels(x2) == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5]
1053+
end
1054+
10231055
y = CategoricalVector{Float64}(b, ordered=ordered)
1024-
append!(x, y)
1025-
@test length(x) == 9
1026-
@test x == [-1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 2.5, 3.0, 3.5]
1027-
@test isordered(x) === ordered
1028-
@test levels(x) == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5]
1056+
x2 = copy(x)
1057+
append!(x2, y)
1058+
@test x2 == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5]
1059+
@test isordered(x2) === ordered
1060+
@test levels(x2) == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5]
10291061

10301062
z1 = view(CategoricalVector{Float64}([100.0, 101.0]), 1)
10311063
z2 = view(CategoricalVector{Float64}([102.0, 103.0]), 1:1)
1032-
append!(x, z1)
1033-
append!(x, z2)
1034-
@test length(x) == 11
1035-
@test x == [-1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 2.5, 3.0, 3.5, 100.0, 102.0]
1036-
@test isordered(x) === ordered
1037-
@test levels(x) == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5, 100.0, 101.0, 102.0, 103.0]
1064+
append!(x2, z1)
1065+
append!(x2, z2)
1066+
@test x2 == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5, 100.0, 102.0]
1067+
@test isordered(x2) === ordered
1068+
@test levels(x2) == [-1.0, 0.0, 1.0, 2.5, 3.0, 3.5, 100.0, 101.0, 102.0, 103.0]
10381069
end
10391070
end
10401071

@@ -1043,54 +1074,76 @@ end
10431074
@testset "String, has missing: $(any(ismissing.(a)))" for a in cases
10441075
x = CategoricalVector{Union{String, Missing}}(a, ordered=ordered)
10451076

1046-
append!(x, x)
1047-
@test x [a; a]
1048-
@test levels(x) == ["a", "b"]
1049-
@test isordered(x) === ordered
1050-
@test length(x) == 6
1077+
x2 = copy(x)
1078+
append!(x2, a)
1079+
@test x2 [a; a]
1080+
@test levels(x2) == ["a", "b"]
1081+
@test isordered(x2) === ordered
1082+
1083+
x2 = copy(x)
1084+
append!(x2, x)
1085+
@test x2 [a; a]
1086+
@test levels(x2) == ["a", "b"]
1087+
@test isordered(x2) === ordered
1088+
1089+
b = ["x2","y",missing]
1090+
x2 = copy(x)
1091+
if ordered
1092+
@test_throws OrderedLevelsException append!(x2, b)
1093+
else
1094+
append!(x2, b)
1095+
@test isordered(x2) === ordered
1096+
@test levels(x2) == ["a", "b", "x2", "y"]
1097+
@test x2 [a; b]
1098+
end
10511099

1052-
b = ["x","y",missing]
10531100
y = CategoricalVector{Union{String, Missing}}(b)
1054-
append!(x, y)
1055-
@test length(x) == 9
1056-
@test isordered(x) === ordered
1057-
@test levels(x) == ["a", "b", "x", "y"]
1058-
@test x [a; a; b]
1101+
x2 = copy(x)
1102+
append!(x2, y)
1103+
@test isordered(x2) === ordered
1104+
@test levels(x2) == ["a", "b", "x2", "y"]
1105+
@test x2 [a; b]
1106+
10591107
z1 = view(CategoricalVector{Union{String, Missing}}([missing, "ex2"]), 1)
10601108
z2 = view(CategoricalVector{Union{String, Missing}}(["ex3", "ex4"]), 1:1)
1061-
append!(x, z1)
1062-
append!(x, z2)
1063-
@test length(x) == 11
1064-
@test isordered(x) === ordered
1065-
@test levels(x) == ["a", "b", "x", "y", "ex2", "ex3", "ex4"]
1066-
@test x [a; a; b; missing; "ex3"]
1109+
x2 = copy(x)
1110+
append!(x2, z1)
1111+
append!(x2, z2)
1112+
@test isordered(x2) === ordered
1113+
@test levels(x2) == ["a", "b", "ex2", "ex3", "ex4"]
1114+
@test x2 [a; missing; "ex3"]
10671115
end
10681116

10691117
@testset "Float64" begin
10701118
a = 0.0:0.5:1.0
10711119
x = CategoricalVector{Union{Float64, Missing}}(a, ordered=ordered)
10721120

1073-
append!(x, x)
1074-
@test length(x) == 6
1075-
@test x == [a; a]
1076-
@test isordered(x) === ordered
1077-
@test levels(x) == [0.0, 0.5, 1.0]
1121+
x2 = copy(x)
1122+
append!(x2, x)
1123+
@test x2 == [a; a]
1124+
@test isordered(x2) === ordered
1125+
@test levels(x2) == [0.0, 0.5, 1.0]
10781126

10791127
b = [2.5, 3.0, missing]
10801128
y = CategoricalVector{Union{Float64, Missing}}(b)
1081-
append!(x, y)
1082-
@test length(x) == 9
1083-
@test x [a; a; b]
1084-
@test isordered(x) === ordered
1085-
@test levels(x) == [0.0, 0.5, 1.0, 2.5, 3.0]
1129+
x2 = copy(x)
1130+
if ordered
1131+
@test_throws OrderedLevelsException append!(x2, b)
1132+
else
1133+
append!(x2, y)
1134+
@test x2 [a; b]
1135+
@test isordered(x2) === ordered
1136+
@test levels(x2) == [0.0, 0.5, 1.0, 2.5, 3.0]
1137+
end
1138+
10861139
z1 = view(CategoricalVector{Union{Float64, Missing}}([missing, 101.0]), 1)
10871140
z2 = view(CategoricalVector{Union{Float64, Missing}}([102.0, 103.0]), 1:1)
1088-
append!(x, z1)
1089-
append!(x, z2)
1090-
@test length(x) == 11
1091-
@test x [a; a; b; missing; 102.0]
1092-
@test isordered(x) === ordered
1093-
@test levels(x) == [0.0, 0.5, 1.0, 2.5, 3.0, 101.0, 102.0, 103.0]
1141+
x2 = copy(x)
1142+
append!(x2, z1)
1143+
append!(x2, z2)
1144+
@test x2 [a; missing; 102.0]
1145+
@test isordered(x2) === ordered
1146+
@test levels(x2) == [0.0, 0.5, 1.0, 101.0, 102.0, 103.0]
10941147
end
10951148
end
10961149

0 commit comments

Comments
 (0)