Hamlet
Hamlet

Reputation: 175

Efficiently construct array with 2-element Array{Float64,1} returned by a function

I have a function, which returns a two dimensional Array:

2-element Array{Float64,1}:
 0.809919
 2.00754

I now want to efficiently sample over it and store all the results in an array with 2 rows and n columns. The problem is that I get a Vector of vectors. How could I flatten it or construct it?

A toy example is the following:

julia> [rand(2) for i=1:3]
3-element Array{Array{Float64,1},1}:
 [0.906644, 0.614673]
 [0.426492, 0.67645]
 [0.473704, 0.726284]

julia> [rand(2)' for i=1:3]
3-element Array{RowVector{Float64,Array{Float64,1}},1}:
 [0.403384 0.431918]
 [0.410625 0.546614]
 [0.224933 0.118778]

And I would like to have the result in a form like this:

julia> [rand(2) rand(2) rand(2)]
2×3 Array{Float64,2}:
 0.360833  0.205969  0.209643
 0.507417  0.317295  0.588516

Actually my dream would be:

julia> [rand(2) rand(2) rand(2)]'
3×2 Array{Float64,2}:
 0.0320955  0.821869
 0.358808   0.26685
 0.230355   0.31273

Any ideas? I know that I could construct it via a for loop, but was looking for a more efficient way.

Thanks!

Upvotes: 0

Views: 53

Answers (2)

Chris Rackauckas
Chris Rackauckas

Reputation: 19132

RecursiveArrayTools.jl has a VectorOfArray type which dispatches in the way you'd want:

julia> using RecursiveArrayTools

julia> A = [rand(2) for i=1:3]
3-element Array{Array{Float64,1},1}:
 [0.957228, 0.104218]
 [0.293985, 0.83882]
 [0.788157, 0.454772]

julia> VectorOfArray(A)'
3×2 Array{Float64,2}:
 0.957228  0.104218
 0.293985  0.83882
 0.788157  0.454772

As for timing:

julia> @benchmark VectorOfArray(A)'
BenchmarkTools.Trial:
  memory estimate:  144 bytes
  allocs estimate:  2
  --------------
  minimum time:     100.658 ns (0.00% GC)
  median time:      111.740 ns (0.00% GC)
  mean time:        127.159 ns (3.29% GC)
  maximum time:     1.360 μs (82.71% GC)
  --------------
  samples:          10000
  evals/sample:     951

VectorOfArray itself is almost no overhead, and the ' uses the Cartesian indexing to be fast.

Upvotes: 2

Arda Aytekin
Arda Aytekin

Reputation: 1301

Something along these lines

using BenchmarkTools

function createSample!(vec::AbstractVector)
  vec .= randn(length(vec))
  return vec
end

function createSamples!(A::Matrix)
  for row in indices(A, 1)
    createSample!(view(A, row, :))
  end
  return A
end

A = zeros(10, 2)

@benchmark createSamples!(A)

might help. The timing on my laptop gives:

Main> @benchmark createSamples!(A)
BenchmarkTools.Trial:
  memory estimate:  1.41 KiB
  allocs estimate:  20
  --------------
  minimum time:     539.104 ns (0.00% GC)
  median time:      581.194 ns (0.00% GC)
  mean time:        694.601 ns (13.34% GC)
  maximum time:     10.324 μs (90.10% GC)
  --------------
  samples:          10000
  evals/sample:     193

Upvotes: 0

Related Questions