An array of empty arrays

Is this the best, or only, way to do this ?

julia> a=Array{Any,1}(5)
5-element Array{Any,1}:
 #undef
 #undef
 #undef
 #undef
 #undef

julia> fill!(a,[])
5-element Array{Any,1}:
 Any[]
 Any[]
 Any[]
 Any[]
 Any[]

just curious. I would have done this in python with

[[]]*5

julia> [[] for i=1:5]
5-element Array{Array{Any,1},1}:
 Any[]
 Any[]
 Any[]
 Any[]
 Any[]
2 Likes

What you have is identical to

julia> fill([], 5)
5-element Array{Array{Any,1},1}:
 Any[]
 Any[]
 Any[]
 Any[]
 Any[]

Note that the arrays you filled in are the same one (i.e. same as [[]] * 5 in python).

As @yuyichao alluded to, there is a difference between the fill and comprehension techniques: do you want an array of the same empty array, or an array of different empty arrays? This will affect what happens if you modify one of the arrays:

julia> a = fill([], 5)
5-element Array{Array{Any,1},1}:
 Any[]
 Any[]
 Any[]
 Any[]
 Any[]

julia> push!(a[1], "hello"); a
5-element Array{Array{Any,1},1}:
 Any["hello"]
 Any["hello"]
 Any["hello"]
 Any["hello"]
 Any["hello"]

julia> b = [[] for i=1:5]
5-element Array{Array{Any,1},1}:
 Any[]
 Any[]
 Any[]
 Any[]
 Any[]

julia> push!(b[1], "hello"); b
5-element Array{Array{Any,1},1}:
 Any["hello"]
 Any[]       
 Any[]       
 Any[]       
 Any[]  

Note that the [[]]*5 construct in Python is similar to fill here, in that it makes a list of 5 references to the same empty list:

In [1]: a = [[]]*5; a
Out[1]: [[], [], [], [], []]

In [2]: a[0].append('hello'); a
Out[2]: [['hello'], ['hello'], ['hello'], ['hello'], ['hello']]
6 Likes

oh my.

I’d forgotten about that distinction even though I had been burned by it in Python.

Yes , I most definitely wanted 5 distinct arrays.

Thank you!

How can I create an empty 0-by-N array?

Let’s say N = 2, then

julia> A = Int64[ [] [] ]
0×2 Array{Int64,2}

julia> vcat(A,[1 2])
1×2 Array{Int64,2}:
 1  2

How do I generalize this code snippet for arbitrary N?

Thanks!

Array{Int}(undef, 0, N)

2 Likes

perfect. I tried Array{Int}(undef, 1, N) the whole time. You would think I would’ve tried replacing the 1 by a 0:smile: … thanks anyway

What is the use case for this? Probably there is a better solution.

The use case is to construct array of multi-indices. Starting from an empty array I gradually want to build up a matrix in which every row represents a multi-index. So, the output of the algorithm is something like this:

julia> A = [1 0 1; 2 0 0; 0 0 3 ]
3×3 Array{Int64,2}:
 1  0  1
 2  0  0
 0  0  3

where every row of A is a multi-index.

The algorithm to construct A is fairly simple:

  1. Define an empty row vector A.
  2. For every candidate multi-index s \in \mathbb{R}^{1 \times N} do:
    • If s satisfies some criterion, append A.
  3. Return A.

You probably want to build this as a Vector of Vectors, and, if necessary, convert to a matrix only at the end.

2 Likes

Or a Vector of SVector (from StaticArrays.jl), if you want to take advantage of compile-time optimizations for the length of your multi-index, not to mention more efficient inline storage in the array. A Vector of SVector can also be converted to a Matrix at the end with a simple reinterpret (no copies) if needed.

3 Likes

Isn’t this what CartesianIndices are for?

1 Like

thanks for the input!

thanks for the pointer. I don’t see the advantage immediately, but I guess reading this should help.

An array of an immutable container with a fixed number of entries (like a CartesianIndex or a StaticArray) is typically vastly more efficient than a generic array of arrays. An array of arrays is essentially like an array of pointers, or a sometype** in C/C++, whereas an array of immutables is like an array of structs that are stored inline. (And the fact that the length of these immutable containers is known to the compiler enables an array of optimization possibilities that can make a big difference for small containers).

2 Likes