From b5246cd3e03f79f3705acb54afccee9e847ddcf6 Mon Sep 17 00:00:00 2001 From: qfl3x Date: Wed, 6 Sep 2023 14:00:20 +0200 Subject: [PATCH 1/7] merge on ComponentVectors --- src/ComponentArrays.jl | 3 ++- src/componentarray.jl | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ComponentArrays.jl b/src/ComponentArrays.jl index a4c96c9c..766c8d35 100644 --- a/src/ComponentArrays.jl +++ b/src/ComponentArrays.jl @@ -2,6 +2,7 @@ module ComponentArrays import ChainRulesCore import StaticArrayInterface, ArrayInterface, Functors +import Base.merge using LinearAlgebra @@ -22,7 +23,7 @@ include("axis.jl") export AbstractAxis, Axis, PartitionedAxis, ShapedAxis, ViewAxis, FlatAxis include("componentarray.jl") -export ComponentArray, ComponentVector, ComponentMatrix, getaxes, getdata, valkeys +export ComponentArray, ComponentVector, ComponentMatrix, getaxes, getdata, valkeys, merge include("componentindex.jl") export KeepIndex diff --git a/src/componentarray.jl b/src/componentarray.jl index 00ed6064..4f6c2efa 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -336,3 +336,15 @@ julia> sum(prod(ca[k]) for k in valkeys(ca)) return :($k) end valkeys(ca::ComponentVector) = valkeys(getaxes(ca)[1]) + +function merge(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) where {T1, T2} + typed_dict = ComponentVector{promote_type(T1, T2)}(cvec1) + for key in valkeys(cvec2) + keyname = getval(key) + val = cvec2[key] + typed_dict = eval(:( ComponentArray($typed_dict, $keyname = $val) )) + end + typed_dict +end + +merge(a::ComponentVector, b::ComponentVector, cs::ComponentVector) = merge(merge(a,b), cs...) \ No newline at end of file From 015d8d2b070c285b4730230e06f0b53ba0ca2817 Mon Sep 17 00:00:00 2001 From: qfl3x Date: Wed, 6 Sep 2023 14:14:59 +0200 Subject: [PATCH 2/7] docs --- src/componentarray.jl | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/componentarray.jl b/src/componentarray.jl index 4f6c2efa..c5fd49ba 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -314,7 +314,7 @@ directly on an `AbstractAxis`. # Examples -```julia-repl +```jldoctest julia> using ComponentArrays julia> ca = ComponentArray(a=1, b=[1,2,3], c=(a=4,)) @@ -337,6 +337,29 @@ julia> sum(prod(ca[k]) for k in valkeys(ca)) end valkeys(ca::ComponentVector) = valkeys(getaxes(ca)[1]) +""" + merge(cvec1::ComponentVector, cvecs::ComponentVector...) + +Construct a new ComponentVector by merging two or more existing ones, in a left-associative +manner. If a key is present in two or more CVectors, the right-most CVector takes priority. +The type of the resulting CVector will be promoted to accomodate all the types of the merged +CVectors + +# Examples +```jldoctest +julia> c1 = ComponentArray(a=1.2, b=2.3) +ComponentVector{Float64}(a = 1.2, b = 2.3) + +julia> c2 = ComponentArray(a=1,h=4) +ComponentVector{Int64}(a = 1, h = 4) + +julia> merge(c1,c2) +ComponentVector{Float64}(a = 1.0, b = 2.3, h = 4.0) + +julia> merge(c2,c1) +ComponentVector{Float64}(a = 1.2, h = 4.0, b = 2.3) +``` +""" function merge(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) where {T1, T2} typed_dict = ComponentVector{promote_type(T1, T2)}(cvec1) for key in valkeys(cvec2) From 7c4c09716acec94dd0349cd44040aa7195005843 Mon Sep 17 00:00:00 2001 From: qfl3x Date: Wed, 6 Sep 2023 14:27:06 +0200 Subject: [PATCH 3/7] Integration with Base.merge --- src/ComponentArrays.jl | 2 +- src/componentarray.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ComponentArrays.jl b/src/ComponentArrays.jl index 766c8d35..f862bb0a 100644 --- a/src/ComponentArrays.jl +++ b/src/ComponentArrays.jl @@ -23,7 +23,7 @@ include("axis.jl") export AbstractAxis, Axis, PartitionedAxis, ShapedAxis, ViewAxis, FlatAxis include("componentarray.jl") -export ComponentArray, ComponentVector, ComponentMatrix, getaxes, getdata, valkeys, merge +export ComponentArray, ComponentVector, ComponentMatrix, getaxes, getdata, valkeys include("componentindex.jl") export KeepIndex diff --git a/src/componentarray.jl b/src/componentarray.jl index c5fd49ba..4a6d772b 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -360,7 +360,7 @@ julia> merge(c2,c1) ComponentVector{Float64}(a = 1.2, h = 4.0, b = 2.3) ``` """ -function merge(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) where {T1, T2} +function Base.merge(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) where {T1, T2} typed_dict = ComponentVector{promote_type(T1, T2)}(cvec1) for key in valkeys(cvec2) keyname = getval(key) @@ -370,4 +370,4 @@ function merge(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) where {T1 typed_dict end -merge(a::ComponentVector, b::ComponentVector, cs::ComponentVector) = merge(merge(a,b), cs...) \ No newline at end of file +Base.merge(a::ComponentVector, b::ComponentVector, cs::ComponentVector) = merge(merge(a,b), cs...) \ No newline at end of file From e7b59991e8bbeeccf888e042815df54364ea2bc7 Mon Sep 17 00:00:00 2001 From: qfl3x Date: Thu, 7 Sep 2023 13:31:12 +0200 Subject: [PATCH 4/7] No more metaprogramming --- src/componentarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/componentarray.jl b/src/componentarray.jl index 4a6d772b..f225b076 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -365,7 +365,7 @@ function Base.merge(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) wher for key in valkeys(cvec2) keyname = getval(key) val = cvec2[key] - typed_dict = eval(:( ComponentArray($typed_dict, $keyname = $val) )) + typed_dict = ComponentArray(typed_dict; keyname=>val) end typed_dict end From 63266048b04ae3ebaebb3ec588d38c799e95d2f3 Mon Sep 17 00:00:00 2001 From: qfl3x Date: Thu, 7 Sep 2023 16:38:02 +0200 Subject: [PATCH 5/7] works --- src/componentarray.jl | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/componentarray.jl b/src/componentarray.jl index f225b076..d18a9541 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -360,14 +360,20 @@ julia> merge(c2,c1) ComponentVector{Float64}(a = 1.2, h = 4.0, b = 2.3) ``` """ -function Base.merge(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) where {T1, T2} - typed_dict = ComponentVector{promote_type(T1, T2)}(cvec1) - for key in valkeys(cvec2) - keyname = getval(key) - val = cvec2[key] - typed_dict = ComponentArray(typed_dict; keyname=>val) +function Base.merge(ca::ComponentVector{T}, ca2::ComponentVector{T}) where T + ax = getaxes(ca) + ax2 = getaxes(ca2) + vks = valkeys(ax[1]) + vks2 = valkeys(ax2[1]) + _p = Vector{T}() + sizehint!(_p, length(c1) + length(ca2)) + for vk in vks + if vk in vks2 + _p = vcat(_p, ca2[vk]) + else + _p = vcat(_p, ca[vk]) + end end - typed_dict + ComponentArray(_p, merged_ax) end - Base.merge(a::ComponentVector, b::ComponentVector, cs::ComponentVector) = merge(merge(a,b), cs...) \ No newline at end of file From bd4658b963b293a6ef9d271c98112b7614d1a6aa Mon Sep 17 00:00:00 2001 From: qfl3x Date: Mon, 11 Sep 2023 10:51:27 +0200 Subject: [PATCH 6/7] Updated --- src/componentarray.jl | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/componentarray.jl b/src/componentarray.jl index d18a9541..314e90b0 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -360,20 +360,6 @@ julia> merge(c2,c1) ComponentVector{Float64}(a = 1.2, h = 4.0, b = 2.3) ``` """ -function Base.merge(ca::ComponentVector{T}, ca2::ComponentVector{T}) where T - ax = getaxes(ca) - ax2 = getaxes(ca2) - vks = valkeys(ax[1]) - vks2 = valkeys(ax2[1]) - _p = Vector{T}() - sizehint!(_p, length(c1) + length(ca2)) - for vk in vks - if vk in vks2 - _p = vcat(_p, ca2[vk]) - else - _p = vcat(_p, ca[vk]) - end - end - ComponentArray(_p, merged_ax) -end -Base.merge(a::ComponentVector, b::ComponentVector, cs::ComponentVector) = merge(merge(a,b), cs...) \ No newline at end of file +Base.merge(ca::ComponentVector) = ca +Base.merge(ca1::ComponentVector, ca2::ComponentVector) = ComponentVector(ca1; ca2...) +Base.merge(ca1::ComponentVector, ca2::ComponentVector, cs::ComponentVector) = merge(merge(ca1,ca2), others...) \ No newline at end of file From fc0db7dc25076d812d0e352429e13001850e7a99 Mon Sep 17 00:00:00 2001 From: qfl3x Date: Fri, 15 Sep 2023 16:40:25 +0200 Subject: [PATCH 7/7] New working prototype --- src/componentarray.jl | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/componentarray.jl b/src/componentarray.jl index 314e90b0..9e3a96fe 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -361,5 +361,33 @@ ComponentVector{Float64}(a = 1.2, h = 4.0, b = 2.3) ``` """ Base.merge(ca::ComponentVector) = ca -Base.merge(ca1::ComponentVector, ca2::ComponentVector) = ComponentVector(ca1; ca2...) -Base.merge(ca1::ComponentVector, ca2::ComponentVector, cs::ComponentVector) = merge(merge(ca1,ca2), others...) \ No newline at end of file +function Base.merge(ca1::ComponentVector{T1}, ca2::ComponentVector{T2}) where {T1,T2} + ax = getaxes(ca1) + ax2 = getaxes(ca2) + vks = valkeys(ax[1]) + vks2 = valkeys(ax2[1]) + idxmap = indexmap(ax[1]) + _p = Vector{promote_type(T1,T2)}() + sizehint!(_p, length(ca1)+length(ca2)) + for vk in vks + if vk in vks2 + _p = vcat(_p, ca2[vk]) + else + _p = vcat(_p, ca1[vk]) + end + end + new_idxmap = Vector{Pair{Symbol, Int64}}([]) + sizehint!(new_idxmap, length(ca2)) + max_val = maximum(idxmap) + for vk in vks2 + if !(vk in vks) + _p = vcat(_p, ca2[vk]) + new_idxmap = vcat(new_idxmap, [getval(vk)=>max_val+1]) + max_val += 1 + end + end + merged_ax = Axis(merge(idxmap, new_idxmap)) + ComponentArray(_p, merged_ax) +end + +Base.merge(ca1::ComponentVector, ca2::ComponentVector, cs::ComponentVector) = merge(merge(ca1,ca2), cs...)