diff --git a/docs/src/dimarrays.md b/docs/src/dimarrays.md index d187e104e..0a70ae212 100644 --- a/docs/src/dimarrays.md +++ b/docs/src/dimarrays.md @@ -58,6 +58,14 @@ fill(7, X(5), Y(10)) fill(7, X(5), Y(10); name=:fill, metadata=Dict()) ``` +== generator construction + +```@ansi dimarray +[x + y for x in X(1:5), y in Y(1:10)] +DimArray(x + y for x in X(1:5), y in Y(1:10)) +DimArray(x + y for x in X(1:5), y in Y(1:10); name=:sum, metadata=Dict()) +``` + ::: ## Constructing DimArray with arbitrary dimension names diff --git a/src/array/array.jl b/src/array/array.jl index df5872902..fd6730b88 100644 --- a/src/array/array.jl +++ b/src/array/array.jl @@ -362,6 +362,7 @@ end DimArray(data, dims, refdims, name, metadata) DimArray(data, dims::Tuple; refdims=(), name=NoName(), metadata=NoMetadata()) + DimArray(gen; kw...) The main concrete subtype of [`AbstractDimArray`](@ref). @@ -372,6 +373,7 @@ moves dimensions to reference dimension `refdims` after reducing operations ## Arguments - `data`: An `AbstractArray`. +- `gen`: A generator expression. Where source iterators are `Dimension`s the dim args or kw is not needed. - `dims`: A `Tuple` of `Dimension` - `name`: A string name for the array. Shows in plots and tables. - `refdims`: refence dimensions. Usually set programmatically to track past @@ -384,6 +386,9 @@ and/or [`Selector`](@ref)s. Indexing `AbstractDimArray` with non-range `AbstractArray` has undefined effects on the `Dimension` index. Use forward-ordered arrays only" +Note that the generator expression syntax requires usage of the semi-colon `;` +to distinguish generator dimensions from keywords. + Example: ```jldoctest; setup = :(using Random; Random.seed!(123)) @@ -415,6 +420,22 @@ julia> A[Near(DateTime(2001, 5, 4)), Between(20, 50)] 40 0.637077 50 0.692235 ``` + +Generator expression: + +```jldoctest +julia> DimArray((x, y) for x in X(1:3), y in Y(1:2); name = :Value) +╭───────────────────────────────────────────╮ +│ 3×2 DimArray{Tuple{Int64, Int64},2} Value │ +├───────────────────────────────────────────┴───── dims ┐ + ↓ X Sampled{Int64} 1:3 ForwardOrdered Regular Points, + → Y Sampled{Int64} 1:2 ForwardOrdered Regular Points +└───────────────────────────────────────────────────────┘ + ↓ → 1 2 + 1 (1, 1) (1, 2) + 2 (2, 1) (2, 2) + 3 (3, 1) (3, 2) +``` """ struct DimArray{T,N,D<:Tuple,R<:Tuple,A<:AbstractArray{T,N},Na,Me} <: AbstractDimArray{T,N,D,A} data::A @@ -467,6 +488,8 @@ function DimArray(f::Function, dim::Dimension; name=Symbol(nameof(f), "(", name( DimArray(f.(val(dim)), (dim,); name) end +DimArray(itr::Base.Generator; kwargs...) = rebuild(collect(itr); kwargs...) + const DimVector = DimArray{T,1} where T const DimMatrix = DimArray{T,2} where T const DimVecOrMat = Union{DimVector,DimMatrix} diff --git a/test/array.jl b/test/array.jl index b44a9bba1..8a73b7793 100644 --- a/test/array.jl +++ b/test/array.jl @@ -473,7 +473,41 @@ end @testset "generator constructor" begin - [(x, y) for x in X(10:10:50), y in Y(0.0:0.1:1.0)] + Xs = X(10:10:50) + Ys = Y(0.0:0.1:1.0) + Zs = Z(100:10:500) + name = :Value + + A = [(x, y) for x in Xs, y in Ys] + @test dims(A) == (Xs, Ys) + @test size(A) == (Xs, Ys) .|> length + + A = DimArray(x for x in Xs) + @test dims(A) == (Xs,) + @test size(A) == (Xs,) .|> length + + A = DimArray(x for x in Xs; name) + @test dims(A) == (Xs,) + @test size(A) == (Xs,) .|> length + @test A.name == name + + A = DimArray((x, y) for x in Xs, y in Ys) + @test dims(A) == (Xs, Ys) + @test size(A) == (Xs, Ys) .|> length + + A = DimArray((x, y) for x in Xs, y in Ys; name) + @test dims(A) == (Xs, Ys) + @test size(A) == (Xs, Ys) .|> length + @test A.name == name + + A = DimArray((x, y, z) for x in Xs, y in Ys, z in Zs) + @test dims(A) == (Xs, Ys, Zs) + @test size(A) == (Xs, Ys, Zs) .|> length + + A = DimArray((x, y, z) for x in Xs, y in Ys, z in Zs; name) + @test dims(A) == (Xs, Ys, Zs) + @test size(A) == (Xs, Ys, Zs) .|> length + @test A.name == name end @testset "ones, zeros, trues, falses constructors" begin