Skip to content

Commit 2e4fe0d

Browse files
authored
add StructArray constructor from slices of an existing array (#159)
* add StructArray constructor from slices of an existing array * disable tests on 1.0 * add to docs * add recursive example to docs
1 parent 031b1bc commit 2e4fe0d

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

docs/src/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ StructArray
1515

1616
```@docs
1717
StructArray(tup::Union{Tuple,NamedTuple})
18+
StructArray(::AbstractArray)
1819
StructArray(::Base.UndefInitializer, sz::Dims)
1920
StructArray(v)
2021
collect_structarray

src/structarray.jl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,58 @@ const StructVector{T, C<:Tup, I} = StructArray{T, 1, C, I}
109109
StructVector{T}(args...; kwargs...) where {T} = StructArray{T}(args...; kwargs...)
110110
StructVector(args...; kwargs...) = StructArray(args...; kwargs...)
111111

112+
"""
113+
StructArray{T}(A::AbstractArray; dims, unwrap=FT->FT!=eltype(A))
114+
115+
Construct a `StructArray` from slices of `A` along `dims`.
116+
117+
The `unwrap` keyword argument is a function that determines whether to
118+
recursively convert fields of type `FT` to `StructArray`s.
119+
120+
!!! compat "Julia 1.1"
121+
This function requires at least Julia 1.1.
122+
123+
```julia-repl
124+
julia> X = [1.0 2.0; 3.0 4.0]
125+
2×2 Array{Float64,2}:
126+
1.0 2.0
127+
3.0 4.0
128+
129+
julia> StructArray{Complex{Float64}}(X; dims=1)
130+
2-element StructArray(view(::Array{Float64,2}, 1, :), view(::Array{Float64,2}, 2, :)) with eltype Complex{Float64}:
131+
1.0 + 3.0im
132+
2.0 + 4.0im
133+
134+
julia> StructArray{Complex{Float64}}(X; dims=2)
135+
2-element StructArray(view(::Array{Float64,2}, :, 1), view(::Array{Float64,2}, :, 2)) with eltype Complex{Float64}:
136+
1.0 + 2.0im
137+
3.0 + 4.0im
138+
```
139+
140+
By default, fields will be unwrapped until they match the element type of the array:
141+
```
142+
julia> StructArray{Tuple{Float64,Complex{Float64}}}(rand(3,2); dims=1)
143+
2-element StructArray(view(::Array{Float64,2}, 1, :), StructArray(view(::Array{Float64,2}, 2, :), view(::Array{Float64,2}, 3, :))) with eltype Tuple{Float64,Complex{Float64}}:
144+
(0.004767505234193781, 0.27949621887414566 + 0.9039320635041561im)
145+
(0.41853472213051335, 0.5760165160827859 + 0.9782723869433818im)
146+
```
147+
"""
148+
StructArray(A::AbstractArray; dims, unwrap)
149+
function StructArray{T}(A::AbstractArray; dims, unwrap=FT->FT!=eltype(A)) where {T}
150+
slices = Iterators.Stateful(eachslice(A; dims=dims))
151+
buildfromslices(T, unwrap, slices)
152+
end
153+
function buildfromslices(::Type{T}, unwrap::F, slices) where {T,F}
154+
if unwrap(T)
155+
buildfromschema(T) do FT
156+
buildfromslices(FT, unwrap, slices)
157+
end
158+
else
159+
return popfirst!(slices)
160+
end
161+
end
162+
163+
112164
function Base.IndexStyle(::Type{S}) where {S<:StructArray}
113165
index_type(S) === Int ? IndexLinear() : IndexCartesian()
114166
end

test/runtests.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,18 @@ end
223223
@test getproperty(t, 2) == [3.0, 2.0]
224224
end
225225

226+
@testset "constructor from slices" begin
227+
if VERSION >= v"1.1"
228+
X = [1.0 2.0; 3.0 4.0]
229+
@test StructArray{Complex{Float64}}(X; dims=1) == [Complex(1.0,3.0), Complex(2.0,4.0)]
230+
@test StructArray{Complex{Float64}}(X; dims=2) == [Complex(1.0,2.0), Complex(3.0,4.0)]
231+
232+
X = [1.0 2.0; 3.0 4.0; 5.0 6.0]
233+
@test StructArray{Tuple{Float64,Complex{Float64}}}(X; dims=1) == [(1.0,Complex(3.0,5.0)), (2.0, Complex(4.0,6.0))]
234+
end
235+
end
236+
237+
226238
struct A
227239
x::Int
228240
y::Int

0 commit comments

Comments
 (0)