Skip to content

Commit 0c5a47a

Browse files
author
Pietro Vertechi
authored
switch to getcolumn and support tables in ND StructArray (#119)
* switch to getcolumn and support tables in ND StructArray * lazy cleanup * more tests * revert changing columns
1 parent ace794f commit 0c5a47a

File tree

5 files changed

+17
-38
lines changed

5 files changed

+17
-38
lines changed

src/StructArrays.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module StructArrays
22

33
using Base: tuple_type_cons, tuple_type_head, tuple_type_tail, tail
4+
using Tables: getcolumn, Tables
45

56
export StructArray, StructVector, LazyRow, LazyRows
67
export collect_structarray, fieldarrays

src/lazy.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ Base.propertynames(c::LazyRow) = propertynames(getfield(c, 1))
1818

1919
function Base.show(io::IO, c::LazyRow)
2020
print(io, "LazyRow")
21-
show(io, to_tup(c))
21+
columns, index = getfield(c, 1), getfield(c, 2)
22+
tup = StructArray(fieldarrays(columns))[index]
23+
show(io, tup)
2224
end
2325

2426
staticschema(::Type{<:LazyRow{T}}) where {T} = staticschema(T)

src/tables.jl

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
using Tables: Tables
1+
Tables.isrowtable(::Type{<:StructArray}) = true
22

3-
Tables.isrowtable(::Type{<:StructVector}) = true
4-
5-
Tables.columnaccess(::Type{<:StructVector}) = true
6-
Tables.columns(s::StructVector) = fieldarrays(s)
7-
8-
Tables.schema(s::StructVector) = Tables.Schema(staticschema(eltype(s)))
3+
Tables.columnaccess(::Type{<:StructArray}) = true
4+
Tables.columns(s::StructArray) = fieldarrays(s)
5+
Tables.getcolumn(s::StructArray, i::Int) = getproperty(s, i)
6+
Tables.schema(s::StructArray) = Tables.Schema(staticschema(eltype(s)))
97

108
function Base.append!(s::StructVector, rows)
119
if Tables.isrowtable(rows) && Tables.columnaccess(rows)
@@ -14,9 +12,7 @@ function Base.append!(s::StructVector, rows)
1412
table = Tables.columns(rows)
1513
isempty(_setdiff(propertynames(s), Tables.columnnames(rows))) ||
1614
_invalid_columns_error(s, rows)
17-
_foreach(propertynames(s)) do name
18-
append!(getproperty(s, name), Tables.getcolumn(table, name))
19-
end
15+
foreachfield(append!, s, table)
2016
return s
2117
else
2218
# Otherwise, fallback to a generic implementation expecting

src/utils.jl

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,6 @@ function buildfromschema(initializer, ::Type{T}, ::Type{NT}) where {T, NT<:Tup}
2121
StructArray{T}(nt)
2222
end
2323

24-
@static if VERSION < v"1.2.0"
25-
@inline _getproperty(v::Tuple, field) = getfield(v, field)
26-
@inline _getproperty(v, field) = getproperty(v, field)
27-
else
28-
const _getproperty = getproperty
29-
end
30-
3124
function _foreachfield(names, L)
3225
vars = ntuple(i -> gensym(), L)
3326
exprs = Expr[]
@@ -36,7 +29,7 @@ function _foreachfield(names, L)
3629
end
3730
for field in names
3831
sym = QuoteNode(field)
39-
args = [Expr(:call, :_getproperty, var, sym) for var in vars]
32+
args = [Expr(:call, :getcolumn, var, sym) for var in vars]
4033
push!(exprs, Expr(:call, :f, args...))
4134
end
4235
push!(exprs, :(return nothing))
@@ -122,13 +115,6 @@ function replace_storage(f, s::StructArray{T}) where T
122115
StructArray{T}(newcols)
123116
end
124117

125-
to_tup(c::T) where {T} = to_tup(c, fieldnames(staticschema(T)))
126-
function to_tup(c, fields::NTuple{N, Symbol}) where N
127-
t = ntuple(i -> getproperty(c, fields[i]), N)
128-
return NamedTuple{fields}(t)
129-
end
130-
to_tup(c, fields::NTuple{N, Int}) where {N} = ntuple(i -> _getproperty(c, fields[i]), N)
131-
132118
astuple(::Type{NamedTuple{names, types}}) where {names, types} = types
133119
astuple(::Type{T}) where {T<:Tuple} = T
134120

@@ -148,8 +134,3 @@ _setdiff(a, b) = setdiff(a, b)
148134
@inline _setdiff(a::Tuple, ::Tuple{}) = a
149135
@inline _setdiff(a::Tuple, b::Tuple) = _setdiff(_exclude(a, b[1]), Base.tail(b))
150136
@inline _exclude(a, b) = foldl((ys, x) -> x == b ? ys : (ys..., x), a; init = ())
151-
152-
# _foreach(f, xs) = foreach(f, xs)
153-
_foreach(f, xs::Tuple) = foldl((_, x) -> (f(x); nothing), xs; init = nothing)
154-
# Note `foreach` is not optimized for tuples yet.
155-
# See: https://github.com/JuliaLang/julia/pull/31901

test/runtests.jl

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,6 @@ cols_infer() = StructArray(([1, 2], [1.2, 2.3]))
318318
@inferred cols_infer()
319319
end
320320

321-
@testset "to_(named)tuple" begin
322-
@test StructArrays.to_tup((1, 2, 3)) == (1, 2, 3)
323-
@test StructArrays.to_tup(2 + 3im) == (re = 2, im = 3)
324-
end
325-
326321
@testset "propertynames" begin
327322
a = StructArray{ComplexF64}((Float64[], Float64[]))
328323
@test sort(collect(propertynames(a))) == [:im, :re]
@@ -341,6 +336,10 @@ end
341336
@test Tables.rowaccess(typeof(s))
342337
@test Tables.columnaccess(s)
343338
@test Tables.columnaccess(typeof(s))
339+
@test Tables.getcolumn(s, 1) == [1]
340+
@test Tables.getcolumn(s, :a) == [1]
341+
@test Tables.getcolumn(s, 2) == ["test"]
342+
@test Tables.getcolumn(s, :b) == ["test"]
344343
@test append!(StructArray([1im]), [(re = 111, im = 222)]) ==
345344
StructArray([1im, 111 + 222im])
346345
@test append!(StructArray([1im]), (x for x in [(re = 111, im = 222)])) ==
@@ -626,11 +625,11 @@ end
626625
rows = LazyRows(s)
627626
@test IndexStyle(rows) isa IndexLinear
628627
@test IndexStyle(typeof(rows)) isa IndexLinear
629-
@test all(t -> StructArrays._getproperty(t, 1) >= 0, s)
628+
@test all(t -> Tables.getcolumn(t, 1) >= 0, s)
630629
@test all(t -> getproperty(t, 1) >= 0, rows)
631630
setproperty!(rows[13], 1, -12)
632631
setproperty!(rows[13], 2, 0)
633-
@test !all(t -> StructArrays._getproperty(t, 1) >= 0, s)
632+
@test !all(t -> Tables.getcolumn(t, 1) >= 0, s)
634633
@test !all(t -> getproperty(t, 1) >= 0, rows)
635634

636635
io = IOBuffer()

0 commit comments

Comments
 (0)