Skip to content

Commit 91202e3

Browse files
author
Pietro Vertechi
committed
added StructureArray
1 parent e48c12d commit 91202e3

File tree

4 files changed

+85
-3
lines changed

4 files changed

+85
-3
lines changed

src/StructureArrays.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
module StructureArrays
22

3-
# package code goes here
3+
import Base:
4+
getindex, setindex!, size, push!, view, getproperty
5+
# linearindexing, push!, size, sort, sort!, permute!, issorted, sortperm,
6+
# summary, resize!, vcat, serialize, deserialize, append!, copy!, view
7+
8+
export StructureArray
9+
10+
const Tup = Union{Tuple, NamedTuple}
11+
12+
include("structurearray.jl")
13+
include("utils.jl")
414

515
end # module

src/structurearray.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
A type that stores an array of structures as a structure of arrays.
3+
# Fields:
4+
- `columns`: a tuple of arrays. Also `columns(x)`
5+
"""
6+
struct StructureArray{T, N, C<:Tup} <: AbstractArray{T, N}
7+
columns::C
8+
9+
function StructureArray{T, N, C}(c) where {T, N, C<:Tup}
10+
length(c) > 0 || error("must have at least one column")
11+
n = size(c[1])
12+
length(n) == N || error("wrong number of dimensions")
13+
for i = 2:length(c)
14+
size(c[i]) == n || error("all columns must have same size")
15+
end
16+
new{T, N, C}(c)
17+
end
18+
end
19+
20+
StructureArray{T}(c::C) where {T, C<:NamedTuple} =
21+
StructureArray{createtype(T, eltypes(C)), length(size(c[1])), C}(c)
22+
StructureArray(c::C) where {C<:NamedTuple} = StructureArray{C}(c)
23+
24+
StructureArray{T}(args...) where {T} = StructureArray{T}(NamedTuple{fields(T)}(args))
25+
26+
27+
28+
columns(s::StructureArray) = getfield(s, :columns)
29+
getproperty(s::StructureArray, key::Symbol) = getfield(columns(s), key)
30+
getproperty(s::StructureArray, key::Int) = getfield(columns(s), key)
31+
32+
size(s::StructureArray) = size(columns(s)[1])
33+
34+
getindex(s::StructureArray, I...) = ith_all(s, I...)

src/utils.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Base: tuple_type_cons, tuple_type_head, tuple_type_tail, tail
2+
3+
eltypes(::Type{Tuple{}}) = Tuple{}
4+
eltypes(::Type{T}) where {T<:Tuple} =
5+
tuple_type_cons(eltype(tuple_type_head(T)), eltypes(tuple_type_tail(T)))
6+
eltypes(::Type{NamedTuple{K, V}}) where {K, V} = eltypes(V)
7+
fields(T) = fieldnames(T)
8+
fields(::Type{<:NamedTuple{K}}) where {K} = K
9+
#@inline ith_all(i, ::Tuple{}) = ()
10+
#@inline ith_all(i, as) = (as[1][i], ith_all(i, tail(as))...)
11+
12+
@generated function ith_all(s::StructureArray{T}, I...) where {T}
13+
args = []
14+
for key in fields(T)
15+
field = Expr(:., :s, Expr(:quote, key))
16+
push!(args, :($field[I...]))
17+
end
18+
Expr(:call, :createinstance, :T, args...)
19+
end
20+
21+
createinstance(::Type{T}, args...) where {T} = T(args...)
22+
createinstance(::Type{T}, args...) where {T<:Tup} = T(args)
23+
24+
createtype(::Type{T}, ::Type{C}) where {T<:NamedTuple{N}, C} where {N} = NamedTuple{N, C}
25+
createtype(::Type{T}, ::Type{C}) where {T, C} = T

test/runtests.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
using StructureArrays
2-
using Base.Test
2+
using Test
33

44
# write your own tests here
5-
@test 1 == 2
5+
t = StructureArray{typeof((a=1.2, b =2.2))}(rand(2,3), rand(2,3));
6+
t[2,2]
7+
# s = t
8+
# T = typeof(t)
9+
# i = 1
10+
# args = []
11+
# for key in fieldnames(T)
12+
# field = Expr(:., :n, Expr(:quote, key))
13+
# push!(args, :($field[i]))
14+
# end
15+
# Expr(:createinstance, :T, args...)
16+
StructureArrays.createtype(NamedTuple{(:a, :b)}, Tuple{Float64, Float64})
17+
s = StructureArray{NamedTuple{(:a, :b)}}([1,2], rand(2));
18+
s = StructureArray((a = rand(2), b = [1,2]))

0 commit comments

Comments
 (0)