# On array comprehensions with \`if\` statements

**URL:** <https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866>\
**Category:** General Usage\
**Tags:** proposal\
**Created:** [October 4, 2018, 11:11am UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866 "2018-10-04T11:11:17Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![gdkrmr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdkrmr/32/2791_2.png) [@gdkrmr](https://discourse.julialang.org/u/gdkrmr)\
**Post date:** [October 4, 2018, 11:11am UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866/1 "2018-10-04T11:11:17Z")

</div>

Array comprehensions are great to construct multidimensional arrays:

1. The default case

```julia
julia> [x * y for x in 1:10, y in 1:10]

10×10 Array{Int64,2}:
  1 2 3 4 5 6 7 8 9 10
  2 4 6 8 10 12 14 16 18 20
  3 6 9 12 15 18 21 24 27 30
  4 8 12 16 20 24 28 32 36 40
  5 10 15 20 25 30 35 40 45 50
  6 12 18 24 30 36 42 48 54 60
  7 14 21 28 35 42 49 56 63 70
  8 16 24 32 40 48 56 64 72 80
  9 18 27 36 45 54 63 72 81 90
 10 20 30 40 50 60 70 80 90 100

```

but I noticed some inconsistencies:

1. Separating for loops does not construct a multidimensional array

```julia
julia> [x * y for x in 1:10 for y in 1:10]

100-element Array{Int64,1}:

```

1. Adding an `if` statement gives a 1d Array.

```julia
julia> [
          x * y 
          for x in 1:10, y in 1:10 if y > 5
       ]

50-element Array{Int64,1}:

```

1. Adding separate for loops AND `if` statements

```julia
julia> [
           x * y 
           for x in 1:10 if x > 4 
           for y in 1:10 if y > 5
       ]

30-element Array{Int64,1}:

```

The ones that make sense to me are the default case and case 2. because subsetting of `x` and `y` is arbitrary.

- The reasoning why case 1. would result in a 1d-Array is not clear to me and
- I would propose that case 3. should result in a 2d array with properly subset columns and rows as a new feature.

---

<div class="post-metadata">

**Author:** ![RaulDurand](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rauldurand/32/2044_2.png) [@RaulDurand](https://discourse.julialang.org/u/RaulDurand)\
**Post date:** [October 4, 2018, 11:25am UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866/3 "2018-10-04T11:25:36Z")

</div>

It was a design choise. More than one for always return a 1d array.

---

<div class="post-metadata">

**Author:** ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)\
**Post date:** [October 4, 2018, 11:52am UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866/4 "2018-10-04T11:52:55Z")

</div>

I think the rules are consistent and quite reasonable:

- multiple `for` statements will always return a vector
- including an `if` clause will always return a vector
- a single `for` with multiple comma separated loops will return a multidimensional array

To construct a multidimensional array with conditionals, just do this:

```julia
julia> [x>4 && y>5 ? x * y : missing for x in 1:10, y in 1:10]
10×10 Array{Union{Missing, Int64},2}:
 missing missing missing missing missing missing missing missing missing missing
 missing missing missing missing missing missing missing missing missing missing
 missing missing missing missing missing missing missing missing missing missing
 missing missing missing missing missing missing missing missing missing missing
 missing missing missing missing missing 30 35 40 45 50
 missing missing missing missing missing 36 42 48 54 60
 missing missing missing missing missing 42 49 56 63 70
 missing missing missing missing missing 48 56 64 72 80
 missing missing missing missing missing 54 63 72 81 90
 missing missing missing missing missing 60 70 80 90 100

```

---

<div class="post-metadata">

**Author:** ![gdkrmr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdkrmr/32/2791_2.png) [@gdkrmr](https://discourse.julialang.org/u/gdkrmr)\
**Post date:** [October 4, 2018, 12:15pm UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866/5 "2018-10-04T12:15:00Z")

</div>

- consistent
- reasonable
- intuitive

This was meant as a proposal to make them better, I edited the working of the initial post to make this clearer.

---

<div class="post-metadata">

**Author:** ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)\
**Post date:** [October 4, 2018, 12:51pm UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866/6 "2018-10-04T12:51:38Z")

</div>

Ad 3. (just some examples for thinking about problem)

It is simple if all rows have same length :

```julia
julia> [x * y for x in [i for i in 1:10 if i > 4] , y in [i for i in 1:10 if i > 5]]

6×5 Array{Int64,2}:
 30 35 40 45 50
 36 42 48 54 60
 42 49 56 63 70
 48 56 64 72 80
 54 63 72 81 90
 60 70 80 90 100

julia> [[x * y for y in 1:10 if y > 5] for x in 1:10 if x > 4]
6-element Array{Array{Int64,1},1}:
 [30, 35, 40, 45, 50] 
 [36, 42, 48, 54, 60] 
 [42, 49, 56, 63, 70] 
 [48, 56, 64, 72, 80] 
 [54, 63, 72, 81, 90] 
 [60, 70, 80, 90, 100]

```

But you could mix `x` and `y` in `if` in nested `for` cycle!

```julia
julia> [[x * y for y in 1:10 if y+x < 15] for x in 1:10 if x > 4]
6-element Array{Array{Int64,1},1}:
 [5, 10, 15, 20, 25, 30, 35, 40, 45]
 [6, 12, 18, 24, 30, 36, 42, 48]    
 [7, 14, 21, 28, 35, 42, 49]        
 [8, 16, 24, 32, 40, 48]            
 [9, 18, 27, 36, 45]                
 [10, 20, 30, 40]   

```

it is not `m×n matrix` here!

First method (above) doesn’t allow this:

```julia
julia> [x * y for x in [i for i in 1:10 if i > 4] , y in [i for i in 1:10 if i+x > 5]]
ERROR: UndefVarError: x not defined

```

---

<div class="post-metadata">

**Author:** ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)\
**Post date:** [October 4, 2018, 1:12pm UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866/7 "2018-10-04T13:12:18Z")

</div>

ad 1.

Think about using local variables. You could do this:

```julia
julia> [
         begin 
           x=i+i+i #=think some complicated expression here =#
           x+x
         end 
         for i in 1:3
       ]
3-element Array{Int64,1}:
  6
 12
 18

```

with current behavior you could simplify it to:

```julia
julia> [
         x+x
         for i in 1:3 
           for x in [i+i+i #=think some complicated expression here =#]
       ]
3-element Array{Int64,1}:
  6
 12
 18

```

You could understand (call it hack if you want 😉 ) expresion

```julia
for x in [val]

```

as special method for binding value of `val` to local variable `x`

I know it is matter of personal preferencies 🙂 I just want to add another POV to problem!

---

<div class="post-metadata">

**Author:** ![gdkrmr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdkrmr/32/2791_2.png) [@gdkrmr](https://discourse.julialang.org/u/gdkrmr)\
**Post date:** [October 4, 2018, 2:21pm UTC](https://discourse.julialang.org/t/on-array-comprehensions-with-if-statements/15866/8 "2018-10-04T14:21:14Z")

</div>

> [@Liso](#):
>
> ```julia
> julia> [x * y for x in [i for i in 1:10 if i < 4] , y in [i for i in 1:10 if i < 5]] 
> 
> 6×5 Array{Int64,2}: 
> 
> ```

That solved my problem, I suspected that I was missing something, thanks!
