StructArrays.jl

Type

StructArrays.StructArrayType
StructArray{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 and setindex! are overloaded to get/set values of type T.
  • getproperty is overloaded to return individual field arrays.

Fields

  • components: a NamedTuple or Tuple of the arrays used by each field. These can be accessed by components(x).
source

Constructors

StructArrays.StructArrayMethod
StructArray{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)
source
StructArrays.StructArrayMethod
StructArray{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 StructArrays.

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)
source
StructArrays.StructArrayMethod
StructArray{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 StructArrays.

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
source
StructArrays.StructArrayMethod
StructArray(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 StructArrays.

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)
source
StructArrays.collect_structarrayFunction
collect_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.

source

Accessors

StructArrays.componentsFunction
components(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])
source

Lazy iteration

StructArrays.LazyRowType
LazyRow(s::StructArray, i)

A lazy representation of s[i]. LazyRow(s, i) does not materialize the ith 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 LazyRows.

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")
source
StructArrays.LazyRowsType
LazyRows(s::StructArray)

An iterator of LazyRows of s.

Examples

julia> map(t -> t.b ^ t.a, LazyRows(t))
2-element Array{String,1}:
 "x"
 "yy"
source

Advanced APIs

StructArrays.append!!Function
dest = 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).

source
StructArrays.replace_storageFunction
StructArrays.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")
source

Interface

StructArrays.staticschemaFunction
StructArrays.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}}
source
StructArrays.createinstanceFunction
StructArrays.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
source

Internals

StructArrays.get_ithFunction
StructArrays.get_ith(cols::Union{Tuple,NamedTuple}, I...)

Form a Tuple of the Ith index of each element of cols, i.e. is equivalent to

map(c -> c[I...], Tuple(cols))
source
StructArrays.map_paramsFunction
StructArrays.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})
source
StructArrays.buildfromschemaFunction
StructArrays.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).

source
StructArrays.bypass_constructorFunction
StructArrays.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.

source
StructArrays.iscompatibleFunction
StructArrays.iscompatible(::Type{S}, ::Type{V}) where {S, V<:AbstractArray}

Check whether element type S can be pushed to a container of type V.

source
StructArrays.maybe_convert_eltFunction
StructArrays.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.

source
StructArrays.findconsistentvalueFunction
findconsistentvalue(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.

source