diff --git a/src/other/index.jl b/src/other/index.jl index 5aea6d382e..1958a87572 100644 --- a/src/other/index.jl +++ b/src/other/index.jl @@ -46,14 +46,36 @@ function names!(x::Index, nms::Vector{Symbol}; makeunique::Bool=false) end function rename!(x::Index, nms) + xbackup = copy(x) + toholder = Dict() for (from, to) in nms from == to && continue # No change, nothing to do - if haskey(x, to) + if !haskey(xbackup, from) + copy!(x.lookup, xbackup.lookup) + x.names .= xbackup.names + error("Tried renaming $from to $to, when $from does not exist in the Index.") + end + if haskey(toholder, to) + copy!(x.lookup, xbackup.lookup) + x.names .= xbackup.names error("Tried renaming $from to $to, when $to already exists in the Index.") end - x.lookup[to] = col = pop!(x.lookup, from) + if haskey(x, to) + toholder[to] = x.lookup[to] + end + if !haskey(toholder, from) && !haskey(x.lookup, from) + copy!(x.lookup, xbackup.lookup) + x.names .= xbackup.names + error("Tried renaming $from to multiple values.") + end + x.lookup[to] = col = haskey(toholder, from) ? pop!(toholder, from) : pop!(x.lookup, from) x.names[col] = to end + if !isempty(toholder) + copy!(x.lookup, xbackup.lookup) + x.names .= xbackup.names + error("Tried renaming to $(first(keys(toholder))), when it already exists in the Index.") + end return x end diff --git a/test/dataframe.jl b/test/dataframe.jl index 5983d43f1e..ee152a6fc8 100644 --- a/test/dataframe.jl +++ b/test/dataframe.jl @@ -1127,6 +1127,16 @@ end @test names(df) == [:A_4, :B_4] @test rename!(x->Symbol(lowercase(string(x))), df) === df @test names(df) == [:a_4, :b_4] + + df = DataFrame(A = 1:3, B = 'A':'C', C = [:x, :y, :z]) + @test rename!(df, :A => :B, :B => :A) === df + @test names(df) == [:B, :A, :C] + @test rename!(df, :A => :B, :B => :A, :C => :D) === df + @test names(df) == [:A, :B, :D] + @test rename!(df, :A => :B, :B => :C, :D => :A) === df + @test names(df) == [:B, :C, :A] + @test rename!(df, :A => :B, :B => :C, :C => :A) === df + @test names(df) == [:C, :A, :B] end @testset "size" begin