# Determining dimension of array via position of "for" and "," in list comprehension

**URL:** <https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027>\
**Category:** General Usage\
**Tags:** array, data\_structures\
**Created:** [October 19, 2021, 11:48am UTC](https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027 "2021-10-19T11:48:02Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![pboes](https://avatars.discourse-cdn.com/v4/letter/p/b5a626/32.png) [@pboes](https://discourse.julialang.org/u/pboes)\
**Post date:** [October 19, 2021, 11:48am UTC](https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027/1 "2021-10-19T11:48:02Z")

</div>

I am new to Julia and noticed the following when playing around with list comprehensions:  
Given some integers `a`, `b`,`c`, the comprehension  
`[[i,j] for i=1:a for j=1:b]`  
returns an `a*b \times 1` array while  
`[[i,j] for i=1:a, j=1:b]`  
returns an `a \times b` array of pairs.

Similarly for three generators,  
`[[i,j,k] for i=1:a for j=1:b for k=1:c]`  
returns an `a*b*c \times 1` array while  
`[[i,j] for i=1:a, j=1:b, k=1:c]`  
returns an `a \times b \times c` array.

This lead me to believe that I could determine the shape of the “outer array” that results from the above kind of comprehensions by connecting the generators (which is how I call the expressions ‘i=1:a’ etc.) by “,” and “for” in the right way. For instance,  
`[[i,j,k] for i=1:a, j=1:b for k=1:c]`  
would return a `a \times b*c` array and  
`[[i,j,k] for i=1:a, j=1:b for k=1:c]`  
a `a*b \times c` dimensional array, etc.

But this is not the case. Instead any call involving more than one “for” expression returns a vector, with the ordering of the elements depending on the position of the “for” expressions.

This brings up two questions:

1. What is the simplest way of generating the kinds of arrays that I would have assumed the above calls generate?
2. Is there a simple rule for determining what kind of vector (or array) a specific combination of “for” and “,” will generate under the actual syntax?

Thanks!

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [October 19, 2021, 1:00pm UTC](https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027/2 "2021-10-19T13:00:11Z")

</div>

You could reshape (which does not allocate):

```julia
julia> x = [[i,j,k] for i=1:2, j=1:3, k=1:4]
2×3×4 Array{Vector{Int64}, 3}:
[:, :, 1] =
 [1, 1, 1] [1, 2, 1] [1, 3, 1]
 [2, 1, 1] [2, 2, 1] [2, 3, 1]

[:, :, 2] =
 [1, 1, 2] [1, 2, 2] [1, 3, 2]
 [2, 1, 2] [2, 2, 2] [2, 3, 2]

[:, :, 3] =
 [1, 1, 3] [1, 2, 3] [1, 3, 3]
 [2, 1, 3] [2, 2, 3] [2, 3, 3]

[:, :, 4] =
 [1, 1, 4] [1, 2, 4] [1, 3, 4]
 [2, 1, 4] [2, 2, 4] [2, 3, 4]

julia> y=reshape(x, (6,4))
6×4 Matrix{Vector{Int64}}:
 [1, 1, 1] [1, 1, 2] [1, 1, 3] [1, 1, 4]
 [2, 1, 1] [2, 1, 2] [2, 1, 3] [2, 1, 4]
 [1, 2, 1] [1, 2, 2] [1, 2, 3] [1, 2, 4]
 [2, 2, 1] [2, 2, 2] [2, 2, 3] [2, 2, 4]
 [1, 3, 1] [1, 3, 2] [1, 3, 3] [1, 3, 4]
 [2, 3, 1] [2, 3, 2] [2, 3, 3] [2, 3, 4]

julia> z=reshape(x, (2, 12))
2×12 Matrix{Vector{Int64}}:
 [1, 1, 1] [1, 2, 1] [1, 3, 1] [1, 1, 2] [1, 2, 2] [1, 3, 2] [1, 1, 3] [1, 2, 3] [1, 3, 3] [1, 1, 4] [1, 2, 4] [1, 3, 4]
 [2, 1, 1] [2, 2, 1] [2, 3, 1] [2, 1, 2] [2, 2, 2] [2, 3, 2] [2, 1, 3] [2, 2, 3] [2, 3, 3] [2, 1, 4] [2, 2, 4] [2, 3, 4]

```

But for my taste, there is an ambiguity in this that I would like to avoid: What exactly is the layout of the 2x12 array supposed to be? If it were me, I would just write out the nested loop and specify “by hand” where each element `[i,j,k]` will go.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 19, 2021, 2:28pm UTC](https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027/3 "2021-10-19T14:28:05Z")

</div>

Nested comprehensions allow for instance:

```julia
a =3; b=5; c=4

M = [[[i,j,k] for i=1:a, j=1:b] for k=1:c] # c-Vector of a x b Matrices

N = [[[i,j,k] for i=1:a] for j=1:b, k=1:c] # b x c Matrix of a-Vectors

```

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 19, 2021, 2:32pm UTC](https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027/4 "2021-10-19T14:32:31Z")

</div>

I’m not entirely sure that mixing `for` and `,` in comprehensions is intentionally allowed. The point of multiple `for`s is to allow the later clauses to depend on the earlier ones, e.g.:

```julia
julia> [(i, j) for i=1:4 for j=i+1:4]
6-element Vector{Tuple{Int64, Int64}}:
 (1, 2)
 (1, 3)
 (1, 4)
 (2, 3)
 (2, 4)
 (3, 4)

```

This must produce a vector of values rather than a matrix since the resulting “shape” isn’t rectangular. When using `,` to separate the clauses, they are independent and the result must be rectangular. As soon as there’s more than one `for` iteration, you cannot in general guarantee rectangular shape, which may be the reasoning for this behavior. @jeff.bezanson implemented it, so he may be able to say more.

---

<div class="post-metadata">

**Author:** ![pboes](https://avatars.discourse-cdn.com/v4/letter/p/b5a626/32.png) [@pboes](https://discourse.julialang.org/u/pboes)\
**Post date:** [October 20, 2021, 7:54am UTC](https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027/5 "2021-10-20T07:54:51Z")

</div>

Nice, that’s clean!

---

<div class="post-metadata">

**Author:** ![pboes](https://avatars.discourse-cdn.com/v4/letter/p/b5a626/32.png) [@pboes](https://discourse.julialang.org/u/pboes)\
**Post date:** [October 20, 2021, 7:58am UTC](https://discourse.julialang.org/t/determining-dimension-of-array-via-position-of-for-and-in-list-comprehension/70027/6 "2021-10-20T07:58:28Z")

</div>

Thanks for the reply. That makes a lot of sense. I guess the best practice is to either work with reshape or with nested comprehensions (as suggested by @rafael.guerra) and in doing so follow the rule to “keep the number of `for`s in every single comprehension to exactly the depth of the nesting of the indices within this comprehension”
