StructArrays.jl
Type
StructArrays.StructArray
— TypeStructArray{T,N,C,I} <: AbstractArray{T, N}
A type that stores an N
-dimensional array of structures of type T
as a structure of arrays.
getindex
andsetindex!
are overloaded to get/set values of typeT
.getproperty
is overloaded to return individual field arrays.
Fields
components
: aNamedTuple
orTuple
of the arrays used by each field. These can be accessed bycomponents(x)
.
Constructors
StructArrays.StructArray
— MethodStructArray{T}((components...)::Union{Tuple, NamedTuple})
StructArray{T}(name1=component1, name2=component2, ...)
Construct a StructArray
of element type T
from the specified field arrays.
StructArray((components...)::Union{Tuple, NamedTuple})
StructArray(name1=component1, name2=component2, ...)
Construct a StructArray
with a Tuple
or NamedTuple
element type from the specified field arrays.
Examples
julia> StructArray{ComplexF64}(([1.0, 2.0], [3.0, 4.0]))
2-element StructArray(::Array{Float64,1}, ::Array{Float64,1}) with eltype Complex{Float64}:
1.0 + 3.0im
2.0 + 4.0im
julia> StructArray{ComplexF64}(re=[1.0, 2.0], im=[3.0, 4.0])
2-element StructArray(::Array{Float64,1}, ::Array{Float64,1}) with eltype Complex{Float64}:
1.0 + 3.0im
2.0 + 4.0im
Any AbstractArray
can be used as a field array
julia> StructArray{Complex{Int64}}(([1, 2], 3:4))
2-element StructArray(::Array{Int64,1}, ::UnitRange{Int64}) with eltype Complex{Int64}:
1 + 3im
2 + 4im
If no element type T
is provided, a Tuple
or NamedTuple
is used:
julia> StructArray((zeros(2,2), ones(2,2)))
2×2 StructArray(::Array{Float64,2}, ::Array{Float64,2}) with eltype Tuple{Float64,Float64}:
(0.0, 1.0) (0.0, 1.0)
(0.0, 1.0) (0.0, 1.0)
julia> StructArray(a=zeros(2,2), b=ones(2,2))
2×2 StructArray(::Array{Float64,2}, ::Array{Float64,2}) with eltype NamedTuple{(:a, :b),Tuple{Float64,Float64}}:
(a = 0.0, b = 1.0) (a = 0.0, b = 1.0)
(a = 0.0, b = 1.0) (a = 0.0, b = 1.0)
StructArrays.StructArray
— MethodStructArray{T}(A::AbstractArray; dims, unwrap=FT->FT!=eltype(A))
Construct a StructArray
from slices of A
along dims
.
The unwrap
keyword argument is a function that determines whether to recursively convert fields of type FT
to StructArray
s.
julia> X = [1.0 2.0; 3.0 4.0]
2×2 Array{Float64,2}:
1.0 2.0
3.0 4.0
julia> StructArray{Complex{Float64}}(X; dims=1)
2-element StructArray(view(::Array{Float64,2}, 1, :), view(::Array{Float64,2}, 2, :)) with eltype Complex{Float64}:
1.0 + 3.0im
2.0 + 4.0im
julia> StructArray{Complex{Float64}}(X; dims=2)
2-element StructArray(view(::Array{Float64,2}, :, 1), view(::Array{Float64,2}, :, 2)) with eltype Complex{Float64}:
1.0 + 2.0im
3.0 + 4.0im
By default, fields will be unwrapped until they match the element type of the array:
julia> StructArray{Tuple{Float64,Complex{Float64}}}(rand(3,2); dims=1)
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}}:
(0.004767505234193781, 0.27949621887414566 + 0.9039320635041561im)
(0.41853472213051335, 0.5760165160827859 + 0.9782723869433818im)
StructArrays.StructArray
— MethodStructArray{T}(undef, dims; unwrap=T->false)
Construct an uninitialized StructArray
with element type T
, with Array
field arrays.
The unwrap
keyword argument is a function that determines whether to recursively convert arrays of element type T
to StructArray
s.
Examples
julia> StructArray{ComplexF64}(undef, (2,3))
2×3 StructArray(::Array{Float64,2}, ::Array{Float64,2}) with eltype Complex{Float64}:
2.3166e-314+2.38405e-314im 2.39849e-314+2.38405e-314im 2.41529e-314+2.38405e-314im
2.31596e-314+2.41529e-314im 2.31596e-314+2.41529e-314im 2.31596e-314+NaN*im
StructArrays.StructArray
— MethodStructArray(A; unwrap = T->false)
Construct a StructArray
from an existing multidimensional array or iterator A
.
The unwrap
keyword argument is a function that determines whether to recursively convert arrays of element type T
to StructArray
s.
Examples
Basic usage
julia> A = rand(ComplexF32, 2,2)
2×2 Array{Complex{Float32},2}:
0.694399+0.94999im 0.422804+0.891131im
0.101001+0.33644im 0.632468+0.811319im
julia> StructArray(A)
2×2 StructArray(::Array{Float32,2}, ::Array{Float32,2}) with eltype Complex{Float32}:
0.694399+0.94999im 0.422804+0.891131im
0.101001+0.33644im 0.632468+0.811319im
From an iterator
julia> StructArray((1, Complex(i, j)) for i = 1:3, j = 2:4)
3×3 StructArray(::Array{Int64,2}, ::Array{Complex{Int64},2}) with eltype Tuple{Int64,Complex{Int64}}:
(1, 1+2im) (1, 1+3im) (1, 1+4im)
(1, 2+2im) (1, 2+3im) (1, 2+4im)
(1, 3+2im) (1, 3+3im) (1, 3+4im)
Recursive unwrapping
julia> StructArray((1, Complex(i, j)) for i = 1:3, j = 2:4; unwrap = T -> !(T<:Real))
3×3 StructArray(::Array{Int64,2}, StructArray(::Array{Int64,2}, ::Array{Int64,2})) with eltype Tuple{Int64,Complex{Int64}}:
(1, 1+2im) (1, 1+3im) (1, 1+4im)
(1, 2+2im) (1, 2+3im) (1, 2+4im)
(1, 3+2im) (1, 3+3im) (1, 3+4im)
StructArrays.collect_structarray
— Functioncollect_structarray(itr; initializer = default_initializer)
Collects itr
into a StructArray
. The user can optionally pass a initializer
, that is to say a function (S, d) -> v
that associates to a type and a size an array of eltype S
and size d
. By default initializer
returns a StructArray
of Array
but custom array types may be used.
Accessors
StructArrays.components
— Functioncomponents(s::StructArray)
Return the field arrays corresponding to the various entry of the struct as a NamedTuple
, or a Tuple
if the struct has no names.
Examples
julia> s = StructArray(rand(ComplexF64, 4));
julia> components(s)
(re = [0.396526, 0.486036, 0.459595, 0.0323561], im = [0.147702, 0.81043, 0.00993469, 0.487091])
Lazy iteration
StructArrays.LazyRow
— TypeLazyRow(s::StructArray, i)
A lazy representation of s[i]
. LazyRow(s, i)
does not materialize the i
th row but returns a lazy wrapper around it on which getproperty
does the correct thing. This is useful when the row has many fields only some of which are necessary. It also allows changing columns in place.
See LazyRows
to get an iterator of LazyRow
s.
Examples
julia> t = StructArray((a = [1, 2], b = ["x", "y"]));
julia> LazyRow(t, 2).a
2
julia> LazyRow(t, 2).a = 123
123
julia> t
2-element StructArray(::Array{Int64,1}, ::Array{String,1}) with eltype NamedTuple{(:a, :b),Tuple{Int64,String}}:
(a = 1, b = "x")
(a = 123, b = "y")
StructArrays.LazyRows
— TypeLazyRows(s::StructArray)
An iterator of LazyRow
s of s
.
Examples
julia> map(t -> t.b ^ t.a, LazyRows(t))
2-element Array{String,1}:
"x"
"yy"
Advanced APIs
StructArrays.append!!
— Functiondest = StructArrays.append!!(dest, itr)
Try to append itr
into a vector dest
, widening the element type of dest
if it cannot hold the elements of itr
. That is to say,
vcat(dest, StructVector(itr)) == append!!(dest, itr)
holds. Note that the dest
argument may or may not be the same object as the returned value.
The state of dest
is unpredictable after append!!
is called (e.g., it may contain some, none or all the elements from itr
).
StructArrays.replace_storage
— FunctionStructArrays.replace_storage(f, s::StructArray)
Change storage type for components: each array v
is replaced by f(v)
. f(v)
is expected to have the same eltype
and size
as v
.
Examples
If PooledArrays is loaded, we can pool all columns of non isbitstype
:
julia> using StructArrays, PooledArrays
julia> s = StructArray(a=1:3, b = fill("string", 3));
julia> s_pooled = StructArrays.replace_storage(s) do v
isbitstype(eltype(v)) ? v : convert(PooledArray, v)
end
3-element StructArray(::UnitRange{Int64}, ::PooledVector{String, UInt32, Vector{UInt32}}) with eltype @NamedTuple{a::Int64, b::String}:
(a = 1, b = "string")
(a = 2, b = "string")
(a = 3, b = "string")
Interface
StructArrays.staticschema
— FunctionStructArrays.staticschema(T)
The default schema for an element type T
. A schema is a Tuple
or NamedTuple
type containing the necessary fields to construct T
. By default, this will have fields with the same names and types as T
.
This can be overloaded for custom types if required, in which case StructArrays.component
and StructArrays.createinstance
should also be defined.
julia> StructArrays.staticschema(Complex{Float64})
NamedTuple{(:re, :im),Tuple{Float64,Float64}}
StructArrays.component
— FunctionStructArrays.component(x, i)
Default to getfield
. It should be overloaded for custom types with a custom schema. See StructArrays.staticschema
.
StructArrays.createinstance
— FunctionStructArrays.createinstance(T, args...)
Construct an instance of type T
from its backing representation. args
here are the elements of the Tuple
or NamedTuple
type specified staticschema(T)
.
julia> StructArrays.createinstance(Complex{Float64}, (re=1.0, im=2.0)...)
1.0 + 2.0im
Internals
StructArrays.get_ith
— FunctionStructArrays.get_ith(cols::Union{Tuple,NamedTuple}, I...)
Form a Tuple
of the I
th index of each element of cols
, i.e. is equivalent to
map(c -> c[I...], Tuple(cols))
StructArrays.map_params
— FunctionStructArrays.map_params(f, T)
Apply f
to each field type of Tuple
or NamedTuple
type T
, returning a new Tuple
or NamedTuple
object.
julia> StructArrays.map_params(T -> Complex{T}, Tuple{Int32,Float64})
(Complex{Int32}, Complex{Float64})
StructArrays.buildfromschema
— FunctionStructArrays.buildfromschema(initializer, T[, S])
Construct a StructArray{T}
with a function initializer
, using a schema S
.
initializer(T)
is a function applied to each field type of S
, and should return an AbstractArray{S}
S
is a Tuple
or NamedTuple
type. The default value is staticschema(T)
.
StructArrays.bypass_constructor
— FunctionStructArrays.bypass_constructor(T, args)
Create an instance of type T
from a tuple of field values args
, bypassing possible internal constructors. T
should be a concrete type.
StructArrays.iscompatible
— FunctionStructArrays.iscompatible(::Type{S}, ::Type{V}) where {S, V<:AbstractArray}
Check whether element type S
can be pushed to a container of type V
.
StructArrays.maybe_convert_elt
— FunctionStructArrays.maybe_convert_elt(T, x)
Element conversion before assignment in a StructArray. By default, this calls convert(T, x)
; however, you can specialize it for other types.
StructArrays.findconsistentvalue
— Functionfindconsistentvalue(f, componenents::Union{Tuple, NamedTuple})
Compute the unique value that f
takes on each component ∈ componenents
. If not all values are equal, return nothing
. Otherwise, return the unique value.