# Comprehension

In this blog let’s look at comprehensions, you can get the notebook here https://gitlab.com/data-science-with-julia/code/-/blob/master/comprehension.ipynb. First we define a range as shown:

```
range = 1:10
```

Output:

```
1:10
```

Now say we want to square the values in the range, we can do it as shown:

```
[value^2 for value in range]
```

Output:

```
10-element Array{Int64,1}:
1
4
9
16
25
36
49
64
81
100
```

Look at the construct of the program, we separate out each item in the `range`

using this statement `for value in range`

, each time the item gets stored in a variable called `value`

, and in `value^2`

we square it, and we capture it in an array by wrapping it all between square brackets like this `[value^2 for value in range]`

. This trickery is called list comprehension.

Below let me introduce to you the `rand()`

function, in the below example we want to generate random number between 1 and 100, so we use `rand(1:100)`

, and we want to generate 10 numbers, so we pass `10`

as the second argument as ten like this `rand(1:100, 10)`

. Type the example below and execute:

```
array = rand(1:100, 10)
```

Output:

```
10-element Array{Int64,1}:
70
41
87
48
54
63
61
100
26
37
```

As you see from the above example, we assign the random numbers to a variable called `array`

. Now let’s use list comprehension to take square root of array as shown:

```
square_root = [value^0.5 for value in array]
```

Output:

```
10-element Array{Float64,1}:
8.366600265340756
6.4031242374328485
9.327379053088816
6.928203230275509
7.3484692283495345
7.937253933193772
7.810249675906654
10.0
5.0990195135927845
6.082762530298219
```

Okay, list comprehension is very powerful feature, but one can take square of array as shown:

```
array.* array
```

Output:

```
10-element Array{Int64,1}:
4900
1681
7569
2304
2916
3969
3721
10000
676
1369
```

So in the above example we do element wise multiplication, for that we use the `.*`

operator. I tried out `array * array`

and hoped that it would work, but it did not.

The dot `.`

means element wise operation. We can do element wise squaring of the `array`

as shown:

```
array.^2
```

Output:

```
10-element Array{Int64,1}:
4900
1681
7569
2304
2916
3969
3721
10000
676
1369
```

All we do add a dot `.`

before `^`

and that’s it. So does it mean list comprehension is dead? Nope we can do some trickery with list comprehension as shown:

```
odd_numbers = [value for value in array if value % 2 != 0]
```

Output:

```
5-element Array{Int64,1}:
41
87
63
61
37
```

Let’s see how the program works. First we take each item in the `array`

and assign it to a variable called `value`

here `for value in array`

, but we do not do that all the time, it happens only when the value is odd as given by `if value % 2 != 0`

, if that happens we take the `value`

and put in in an Array like this `[value .....]`

. So we have complete program as shown here `[value for value in array if value % 2 != 0]`

. So what we are doing is filtering the odd numbers, nothing else.

# Generator Comprehension

Just like list comprehension, in which things are wrapped around by square braces, we use round braces for a thing called generator comprehension. If you look at the example below, we do squaring elements of `range`

:

```
squares = (el^2 for el in range)
```

Output:

```
Base.Generator{typeof(range),var"#3#4"}(var"#3#4"(), range)
```

but we do it inside round braces, so we get an output as shown above. That is squares are not evaluated unless absolutely necessary. So to force the evaluation we run the code below

```
join(squares, ", ")
```

Output:

```
"1, 4, 9, 16, 25, 36, 49, 64, 81, 100"
```

Where the method `join()`

, joins the element of passed collection `squares`

in this case with a string `", "`

.

# Permutation

If we roll two dice, let’s see what permutations we get. Type the code below and execute:

```
dice_range = 1:6
# Finding permuation for roll of two dice
dice_permuations = [(x, y) for x = dice_range, y = dice_range]
```

Output:

```
6×6 Array{Tuple{Int64,Int64},2}:
(1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6)
(2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6)
(3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (3, 6)
(4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (4, 6)
(5, 1) (5, 2) (5, 3) (5, 4) (5, 5) (5, 6)
(6, 1) (6, 2) (6, 3) (6, 4) (6, 5) (6, 6)
```

So let’s see how the code works. So we are using list comprehension, and we are wrapping the output in square brackets `[]`

, we are wrapping a Tuple inside a list `[(x, y)]`

, and the Tuple is fed by variables `x`

and `y`

. These `x`

and `y`

take their values in an iterative manner from `dice_range`

that ranges from 1 to 6 here `for x = dice_range, y = dice_range`

. So this concise piece of code generates us a 6X6 array with all permutations of `x`

and `y`

. Below we check the size of the permutation as though we don’t trust Julia:

```
size(dice_permuations)
```

Output:

```
(6, 6)
```

# Flattened Comprehension

The comprehension discussed above returned a rank 2 matrix, but what if want to generate a flattened one? See the example below:

```
flattened_permuations = [(x, y) for x = dice_range for y = dice_range]
```

Output:

```
36-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(1, 6)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(2, 5)
(2, 6)
(3, 1)
⋮
(5, 1)
(5, 2)
(5, 3)
(5, 4)
(5, 5)
(5, 6)
(6, 1)
(6, 2)
(6, 3)
(6, 4)
(6, 5)
(6, 6)
```

In the above example we simply use 2 `for`

’s like this `for x = dice_range for y = dice_range`

. This generates us a vector of Tuple’s rather than a matrix as in the previous example. Now let’s check its size to conform it’s a vector:

```
size(flattened_permuations)
```

Output:

```
(36,)
```