1
00:00:05,720 --> 00:00:10,560
Alright, so firstly, before we move on to conditional comprehensions, I just want to point out that I've created

2
00:00:10,560 --> 00:00:15,870
a new project, comprehensions, and I've just removed all the music files that were hanging around from

3
00:00:15,870 --> 00:00:22,460
a previous project, just to clear things up. So you can grab a download of that file from the last video.

4
00:00:22,560 --> 00:00:26,580
That's got everything that you're seeing at the start of this video. So moving on as

5
00:00:26,580 --> 00:00:29,940
I mentioned - conditional comprehensions.

6
00:00:30,000 --> 00:00:35,750
So it's actually very common to have an if clause inside a for loop, and we can do that with comprehensions

7
00:00:35,760 --> 00:00:36,760
as well.

8
00:00:36,760 --> 00:00:42,930
Now in one of the earlier videos about lists, we created a menu and then we printed out all the meals that

9
00:00:42,930 --> 00:00:44,610
didn't contain spam.

10
00:00:44,850 --> 00:00:47,230
So I'm going to put that code into a new file here.

11
00:00:47,550 --> 00:00:52,040
But also that file is available in the resources section of this video if you want to grab it and you

12
00:00:52,050 --> 00:00:53,590
don't care to type it in again.

13
00:00:54,060 --> 00:00:55,550
So the file I'm going to create here,

14
00:00:57,240 --> 00:00:59,100
I'm going to call it condcomp,

15
00:01:02,130 --> 00:01:03,900
conditional comprehensions.

16
00:01:04,379 --> 00:01:08,120
OK, I'm going to paste that code in, like so,

17
00:01:09,780 --> 00:01:12,620
and we'll just run the program to make sure that it works still.

18
00:01:13,820 --> 00:01:18,120
And you can see it's working correctly down the bottom. That's giving us all the meals without spam.

19
00:01:18,120 --> 00:01:23,750
Now we can do the same thing with a comprehension by adding an if clause to that comprehension.

20
00:01:23,880 --> 00:01:24,890
So let's go and do that,

21
00:01:24,890 --> 00:01:27,120
starting on line 17, and we'll type

22
00:01:27,120 --> 00:01:34,850
meals equals left square brackets meal for meal in menu.

23
00:01:35,460 --> 00:01:39,230
And then the if clause is, if double quotes spam double quotes,

24
00:01:39,640 --> 00:01:43,510
basically spam in double quotes, not in meal.

25
00:01:43,830 --> 00:01:51,900
Then we've got our closing right square bracket, and we can print out the result, meals. So when I to run that, we should

26
00:01:51,900 --> 00:01:57,100
get the correct meals in our lists, and you can see down here that that has actually happened.

27
00:01:58,540 --> 00:02:04,510
So our comprehension now specifies a filter, as you can see on screen, extending the incomplete definition

28
00:02:04,660 --> 00:02:05,910
that we saw earlier.

29
00:02:06,160 --> 00:02:12,010
Now a comprehension has an expression, just the value of meal in this example, but the expression can be

30
00:02:12,010 --> 00:02:13,310
much more complicated.

31
00:02:13,750 --> 00:02:19,330
Next is the iteration, and that can be followed by one or more filters.

32
00:02:19,330 --> 00:02:25,290
Alright so back in IntelliJ. So, I'm not making the comprehensions print out the values because I've showed

33
00:02:25,470 --> 00:02:26,770
you how to do that earlier.

34
00:02:27,010 --> 00:02:33,090
It's actually clearer here to see what the comprehension produces if we just print out the list itself.

35
00:02:33,100 --> 00:02:38,800
Now I could get exactly the same behavior by appending the meals to a list in the for loop, but that

36
00:02:38,800 --> 00:02:41,400
doesn't really add anything to the explanation.

37
00:02:41,410 --> 00:02:43,560
So just to be clear though, I'll quickly do that.

38
00:02:43,560 --> 00:02:50,170
So I'm going to add a line here, above the for, the for loops, so meals equals, creating an empty list, left and

39
00:02:50,170 --> 00:02:51,970
right square brackets.

40
00:02:51,970 --> 00:03:01,370
Then after the 'if spam not in meal' we can put meals dot append meal.

41
00:03:02,250 --> 00:03:06,990
And what I could do then is indent this one back to print meal, to make that then print

42
00:03:07,060 --> 00:03:13,570
meals. Run it and basically we've got the same result, but that's just taking up more time and really doesn't

43
00:03:13,570 --> 00:03:15,460
add anything to the explanation.

44
00:03:15,460 --> 00:03:15,690
Alright,

45
00:03:15,700 --> 00:03:22,120
so what we've done there in the comprehension, well all I've done is add an if clause to the end, and I'm talking

46
00:03:22,120 --> 00:03:23,650
about this code on line 19.

47
00:03:24,000 --> 00:03:27,910
In fact the comprehension reads almost the same as the for loop.

48
00:03:28,000 --> 00:03:33,650
Now the values added to the list will be meal for each meal in menu, and we're adding the condition

49
00:03:33,820 --> 00:03:37,180
if spam and double quotes not in meal.

50
00:03:37,190 --> 00:03:42,570
Now that's probably straightforward but it may not be obvious exactly what's happening here.

51
00:03:42,700 --> 00:03:48,460
Now looking at it at face value it looks like a normal condition using if, but in fact it's more like

52
00:03:48,460 --> 00:03:49,600
a filter.

53
00:03:49,780 --> 00:03:54,960
So the meal here is only included in the list if the condition is true,

54
00:03:55,300 --> 00:03:57,130
otherwise it's skipped.

55
00:03:57,340 --> 00:03:58,830
So does the difference matter?

56
00:03:59,080 --> 00:04:04,540
Well the answer to that is, it can do. So I modified the loop earlier, so lets just add the message to the list

57
00:04:04,540 --> 00:04:05,960
instead of printing it.

58
00:04:06,010 --> 00:04:08,320
So back up here, we've got meal dot append,

59
00:04:08,330 --> 00:04:13,930
if not spam, but we can put an else in here,

60
00:04:14,150 --> 00:04:19,360
and I'll put meals dot append. Because we're not printing it out here,

61
00:04:19,510 --> 00:04:25,870
we'll just put an entry to make it obvious a meal was skipped. Alright

62
00:04:25,870 --> 00:04:26,070
so run it,

63
00:04:28,990 --> 00:04:35,420
and you can see that that seems to behave as we'd expect it to behave, showing the entries that have been skipped,

64
00:04:35,420 --> 00:04:39,620
and also showing the entries that were included because they weren't spam.

65
00:04:39,620 --> 00:04:42,620
So that's a very common thing to see in a for loop.

66
00:04:42,890 --> 00:04:46,390
So how do we get our comprehensions to do the same thing?

67
00:04:46,430 --> 00:04:52,360
So at first attempt you might come back to that comprehension which is now line 21, and add the else

68
00:04:52,370 --> 00:04:57,850
clause here. So you might put else and double quotes, a meal.

69
00:05:01,590 --> 00:05:02,560
I can't type!

70
00:05:02,860 --> 00:05:06,130
But obviously, that's giving us an error so there's no point me continuing on to that.

71
00:05:06,130 --> 00:05:08,120
So how do we actually fix this?

72
00:05:08,170 --> 00:05:11,100
Well the answer is we can't.

73
00:05:11,230 --> 00:05:18,220
The if in our comprehension is being used to filter the meals, and you can't have an else clause in there.

74
00:05:18,220 --> 00:05:20,910
So the key here to keep in mind is the word filter.

75
00:05:21,250 --> 00:05:27,070
So we're not making up new values, we're just iterating over the sequence and allowing through certain values

76
00:05:27,400 --> 00:05:29,090
based on that condition.

77
00:05:29,100 --> 00:05:31,470
Now if a value meets the condition, it's allowed in,

78
00:05:31,570 --> 00:05:36,150
otherwise it's not. So filter either lets things through or it doesn't.

79
00:05:36,340 --> 00:05:41,330
So in other words it can't be used to produce anything else, which is why we can't use an else clause.

80
00:05:41,360 --> 00:05:42,150
We're getting an error.

81
00:05:42,400 --> 00:05:47,580
But don't despair because there's something else we can do in this case.

82
00:05:47,590 --> 00:05:52,180
Now I don't want to digress too much at the moment, so I'll cover that a bit later. For now though,

83
00:05:52,210 --> 00:05:54,810
I'm just going to undo that change and we'll look at that

84
00:05:54,820 --> 00:05:57,660
if filter in a bit more detail.

85
00:05:58,440 --> 00:06:01,530
OK so what if we didn't want chicken in the meal either?

86
00:06:01,870 --> 00:06:04,720
Now this syntax is going to look a bit strange but we can actually do this.

87
00:06:04,720 --> 00:06:16,100
We can put, we've got our 'if spam not in meal', we can come along on the end here and put 'if chicken not in meal',

88
00:06:16,660 --> 00:06:18,670
remembering that we had chicken in the output before.

89
00:06:18,850 --> 00:06:23,270
Run it this time and you can see that the chicken has been successfully removed.

90
00:06:23,650 --> 00:06:28,610
Now you may see filters written that way, and it's actually certainly perfectly valid.

91
00:06:28,630 --> 00:06:34,180
In fact it can be a good way to make complicated conditions more readable, but a more usual way to write

92
00:06:34,180 --> 00:06:35,380
that would be to use

93
00:06:35,380 --> 00:06:44,920
and. So lets duplicate this line and we'll comment out the first one, and we're going to change this line. And

94
00:06:44,920 --> 00:06:52,990
the obvious change here would be 'if spam not in meal', and instead of 'if' there, we use the word 'and', 'and chicken not

95
00:06:52,990 --> 00:06:53,920
in meal'.

96
00:06:54,060 --> 00:06:59,340
And if we run that just to confirm that it works, you can see we get the same result there -

97
00:06:59,360 --> 00:07:01,440
we've got no spam but also no chicken.

98
00:07:01,780 --> 00:07:07,240
So we've presented many alternative ways of doing the same thing throughout the course, and a common question

99
00:07:07,240 --> 00:07:10,090
we get asked is "which should I use"?

100
00:07:10,180 --> 00:07:11,990
Now sometimes that's easy to answer

101
00:07:12,160 --> 00:07:14,850
and generally, I'll mention that in the videos.

102
00:07:15,070 --> 00:07:17,150
But other times it really doesn't make a difference,

103
00:07:17,320 --> 00:07:21,760
and this is one of those other times. Use whichever form here makes the most sense.

104
00:07:21,940 --> 00:07:27,550
You can even mix them, which is what I meant when I said it can make complicated conditions more readable.

105
00:07:27,550 --> 00:07:29,240
Now to see what I mean by that,

106
00:07:29,560 --> 00:07:32,480
let's say we get a fussy customer to our restaurant.

107
00:07:32,500 --> 00:07:36,340
Now they love spam and they love eggs. They also like bacon and sausage,

108
00:07:36,340 --> 00:07:39,890
but for some reason they can't stand bacon with sausage.

109
00:07:39,940 --> 00:07:45,460
Now there's quite a few ways to phrase a condition like that, but it comes down to; choose meals with

110
00:07:45,460 --> 00:07:46,850
spam or eggs,

111
00:07:46,860 --> 00:07:50,810
meals can contain bacon or sausage, as long as they're not together.

112
00:07:50,980 --> 00:07:55,540
Now reading that as two separate filters makes the code a bit more readable.

113
00:07:55,540 --> 00:08:00,810
So let's see the code which I'm going to add to the end of this program. Close down the run window for now.

114
00:08:00,810 --> 00:08:02,590
So we'll start on line 25 here,

115
00:08:02,920 --> 00:08:10,290
fussy meals equals left and right square bracket, or brackets, meal for meal in menu.

116
00:08:10,590 --> 00:08:28,030
And if spam in double quotes, or eggs in double quote, quotes, in meal, if not, parentheses double quote bacon double quote

117
00:08:28,170 --> 00:08:37,520
in meal and sausage in meal.

118
00:08:38,409 --> 00:08:45,690
And then we want a right parentheses there to close off and then our right square bracket - and I made a typo there,

119
00:08:45,720 --> 00:08:49,160
that should be in meal, if spam in meal.

120
00:08:49,180 --> 00:08:50,880
So there's the code, fussy meals equals,

121
00:08:54,400 --> 00:08:55,180
and that's a bit better.

122
00:08:55,280 --> 00:08:55,620
OK,

123
00:08:55,650 --> 00:08:59,520
so there's our code, fussy meals equals meal for meal in menu.

124
00:08:59,730 --> 00:09:07,380
If spam in double quotes in meal, or eggs in double quote in meal, and another condition, if not, then we've got

125
00:09:07,750 --> 00:09:15,240
parentheses there, bacon in double quotes in meal and sausage in meal, then right parentheses and a square bracket.

126
00:09:15,710 --> 00:09:17,970
OK now let's print it out.

127
00:09:20,050 --> 00:09:22,140
OK, we'll run it.

128
00:09:22,970 --> 00:09:27,750
So they should all contain spam and eggs, as you can see here, but you can't see any, I can't see any,

129
00:09:28,070 --> 00:09:31,410
that have actually got both bacon and sausage.

130
00:09:31,470 --> 00:09:40,440
So basically you can see with that line, that the first one lets through any meals, that's the first part,

131
00:09:40,600 --> 00:09:47,480
so lets through any meals that contain spam or eggs. We've used or instead of and there, so either of those. Then

132
00:09:47,490 --> 00:09:55,510
the second one, the second filter here, filters out any meal that contains both bacon and sausages in a meal.

133
00:09:55,570 --> 00:10:01,560
So it's not a trivial condition, and specifying it as two separate filters makes it easier to see what's

134
00:10:01,560 --> 00:10:02,770
going on.

135
00:10:02,850 --> 00:10:08,110
So what I'll do though, just to show you to be consistent here, and I might just move this over a bit so we've got a bit

136
00:10:08,110 --> 00:10:08,970
more space,

137
00:10:11,110 --> 00:10:16,020
I'm going to actually paste in the equivalent code using a single filter,

138
00:10:16,530 --> 00:10:19,420
and again, you can get this pasted in code from the resources section of this video.

139
00:10:24,450 --> 00:10:27,580
Firstly we'll just run it to make sure we've got the equivalent results,

140
00:10:27,670 --> 00:10:29,650
and you can see the results are identical.

141
00:10:29,790 --> 00:10:31,310
And in terms of the actual code,

142
00:10:34,500 --> 00:10:37,220
we have got a warning here about the line being too long.

143
00:10:37,740 --> 00:10:40,730
And what we can do and the quickest way of solving that; Code, Reformat.

144
00:10:43,780 --> 00:10:44,660
So we'll get IntelliJ to

145
00:10:44,660 --> 00:10:45,230
help us,

146
00:10:45,240 --> 00:10:48,160
and you can see that's nicely formatted things for us.

147
00:10:48,560 --> 00:10:51,080
And let's do the same here, just to make it a little bit easier to read.

148
00:10:58,580 --> 00:10:59,650
I'll just delete that comment.

149
00:10:59,840 --> 00:11:00,090
Alright,

150
00:11:00,090 --> 00:11:01,400
so what have we got here.

151
00:11:01,980 --> 00:11:04,750
Well this is the code that I've pasted in on line 29.

152
00:11:05,360 --> 00:11:10,620
That's now using a single filter instead of the double, or the two filters we used on the code, with the

153
00:11:10,620 --> 00:11:12,190
code on line 25.

154
00:11:12,440 --> 00:11:16,620
And again we ran the code, you can see down the bottom - it performs the same result each time.

155
00:11:16,920 --> 00:11:22,260
So the second form, using a single complex condition, which you can see that I've used again on line 29,

156
00:11:22,500 --> 00:11:28,230
that's harder to understand, and it was even harder to write correctly first time. The parentheses around

157
00:11:28,230 --> 00:11:30,450
the first condition are essential.

158
00:11:30,450 --> 00:11:35,630
Now of course, if you find the second method more readable, then by all means write your code that way.

159
00:11:35,950 --> 00:11:39,650
In terms of performance though, there's nothing to choose between either one.

160
00:11:39,660 --> 00:11:44,580
Alright, so I'm going to stop the video here. In the next one, we're going to review using if as an expression,

161
00:11:44,910 --> 00:11:50,340
and then see how we can solve that earlier problem, using else in the comprehension to add something that

162
00:11:50,340 --> 00:11:52,540
doesn't appear in the original sequence.

163
00:11:52,560 --> 00:11:53,970
So I'll see you in the next video.

