1 00:00:00,840 --> 00:00:02,930 - [Narrator] In this video, we'd like to present 2 00:00:02,930 --> 00:00:05,760 some additional functions that are 3 00:00:05,760 --> 00:00:08,860 capable of processing sequences of elements. 4 00:00:08,860 --> 00:00:11,670 We'll use lists for demonstration purposes, 5 00:00:11,670 --> 00:00:14,850 but any sequence can be processed by the functions 6 00:00:14,850 --> 00:00:16,810 that I'm about to demonstrate to you. 7 00:00:16,810 --> 00:00:18,610 And part of what I'd like to do here 8 00:00:18,610 --> 00:00:22,440 is revisit the min and max functions, 9 00:00:22,440 --> 00:00:25,490 which by the way are also reductions in 10 00:00:25,490 --> 00:00:28,060 functional style programming because they look at 11 00:00:28,060 --> 00:00:30,630 a sequence of elements and give you back one result, 12 00:00:30,630 --> 00:00:33,040 the minimum or the maximum respectively. 13 00:00:33,040 --> 00:00:34,990 Now, in each of those functions cases, 14 00:00:34,990 --> 00:00:37,830 the default way that they work is to 15 00:00:37,830 --> 00:00:40,910 compare objects in their default manner. 16 00:00:40,910 --> 00:00:43,260 So, if we're talking about integers, 17 00:00:43,260 --> 00:00:44,800 it's going to look at two integers 18 00:00:44,800 --> 00:00:48,196 and the smaller one is going to be the minimum 19 00:00:48,196 --> 00:00:51,200 or the larger one is going to be the maximum. 20 00:00:51,200 --> 00:00:53,810 On the other hand, if I'm looking at strings, 21 00:00:53,810 --> 00:00:56,800 smaller and larger depends on the underlying 22 00:00:56,800 --> 00:01:01,290 character codes of the characters within those strings. 23 00:01:01,290 --> 00:01:04,980 So for example, if I go ahead and compare Red 24 00:01:04,980 --> 00:01:09,980 to the string orange with a lowercase "o", 25 00:01:10,420 --> 00:01:14,110 clearly orange comes before red alphabetically 26 00:01:14,110 --> 00:01:18,930 but numerically, capital "R" comes before lowercase "o" 27 00:01:18,930 --> 00:01:20,840 in the underlying character set, 28 00:01:20,840 --> 00:01:24,880 which is the default way in which strings 29 00:01:24,880 --> 00:01:26,670 are going to be compared in Python. 30 00:01:26,670 --> 00:01:29,340 So, I get true here because capital "R" 31 00:01:29,340 --> 00:01:32,310 is less than lowercase "o" and we can confirm that, 32 00:01:32,310 --> 00:01:34,575 by the way, with a function called ord, 33 00:01:34,575 --> 00:01:36,600 that's built into the language, 34 00:01:36,600 --> 00:01:38,720 which gives you back, for a given character, 35 00:01:38,720 --> 00:01:42,640 the underlying numeric code in the Unicode character set. 36 00:01:42,640 --> 00:01:47,177 So, the ordinal value of the character "R" is 82 37 00:01:47,177 --> 00:01:49,890 and if I recall that and put an "o" in there, 38 00:01:49,890 --> 00:01:52,610 you can see that lowercase "o" is 111. 39 00:01:52,610 --> 00:01:57,610 So, indeed, this is true because 82 is less than 111. 40 00:01:58,390 --> 00:02:02,158 Now, what I'd like to do in this example to start out, 41 00:02:02,158 --> 00:02:06,760 is put in a list of strings with various 42 00:02:06,760 --> 00:02:09,900 upper and lowercase strings in it, 43 00:02:09,900 --> 00:02:13,390 and I want to demonstrate the min and max functions 44 00:02:13,390 --> 00:02:17,335 once again, this time providing a second argument 45 00:02:17,335 --> 00:02:21,710 that says how to compare the items. 46 00:02:21,710 --> 00:02:25,500 So, min is capable of receiving a sequence of values 47 00:02:25,500 --> 00:02:28,240 and giving you the smallest element in that sequence. 48 00:02:28,240 --> 00:02:31,659 But if you supply the key, keyword argument, 49 00:02:31,659 --> 00:02:34,960 in this case we're providing it as a lambda expression, 50 00:02:34,960 --> 00:02:37,681 but it could be some function that returns a value. 51 00:02:37,681 --> 00:02:41,193 What's going to happen is it will use this lambda expression 52 00:02:41,193 --> 00:02:46,193 to help compare the elements in the sequence. 53 00:02:46,330 --> 00:02:48,310 So, here the lambda is going to take 54 00:02:48,310 --> 00:02:51,910 each string that we give it and give us back 55 00:02:51,910 --> 00:02:55,380 the lowercase only version of that string. 56 00:02:55,380 --> 00:02:58,080 So, even though I have upper and lowercase letters 57 00:02:58,080 --> 00:03:00,350 in the strings in the original collection, 58 00:03:00,350 --> 00:03:03,240 it's going to process red with a lowercase "r", 59 00:03:03,240 --> 00:03:06,870 yellow with a lowercase "y", and b with a lowercase "b". 60 00:03:06,870 --> 00:03:09,360 And then, based on that, we'll figure out 61 00:03:09,360 --> 00:03:11,650 the smallest item in the collection, 62 00:03:11,650 --> 00:03:16,250 which is blue alphabetically as opposed to numerically. 63 00:03:16,250 --> 00:03:18,080 It's still comparing them numerically 64 00:03:18,080 --> 00:03:20,910 but now that all the letters are lowercase, 65 00:03:20,910 --> 00:03:23,900 it's able to give me the alphabetic ordering 66 00:03:23,900 --> 00:03:27,210 that I'm looking for in this particular example. 67 00:03:27,210 --> 00:03:30,870 And similarly, I can go ahead and calculate the max. 68 00:03:30,870 --> 00:03:34,070 So again, based on these strings here, 69 00:03:34,070 --> 00:03:37,000 if we convert them all to lowercase letters first, 70 00:03:37,000 --> 00:03:39,050 then we can figure out alphabetically 71 00:03:39,050 --> 00:03:40,690 which is the largest string, 72 00:03:40,690 --> 00:03:43,813 which in this case is the string yellow. 73 00:03:46,220 --> 00:03:48,770 Now, there are a couple of other sequence processing 74 00:03:48,770 --> 00:03:52,540 functions that could come in handy in a number of scenarios, 75 00:03:52,540 --> 00:03:55,350 so I just wanted to introduce those to you as well. 76 00:03:55,350 --> 00:03:58,740 So, first let me go ahead and create a list called numbers 77 00:03:58,740 --> 00:04:01,312 for the next piece of this demonstration. 78 00:04:01,312 --> 00:04:03,310 In this demonstration, I'd like to 79 00:04:03,310 --> 00:04:05,930 demonstrate the reversed function, 80 00:04:05,930 --> 00:04:08,470 which takes as it's argument a sequence 81 00:04:08,470 --> 00:04:13,470 and gives you back a new sequence in reverse order. 82 00:04:13,520 --> 00:04:16,570 So, let me paste in a statement here for us to look at. 83 00:04:16,570 --> 00:04:19,870 Here is the reverse call that I'm introducing. 84 00:04:19,870 --> 00:04:22,860 Now, reversed like filter and map 85 00:04:22,860 --> 00:04:24,950 is going to give you back an iterator. 86 00:04:24,950 --> 00:04:27,230 So again, this is a lazy function, 87 00:04:27,230 --> 00:04:32,150 it does nothing until you iterate over it's results. 88 00:04:32,150 --> 00:04:34,930 So, it does nothing other than create the iterator, 89 00:04:34,930 --> 00:04:38,150 I should say, until you iterate over those results. 90 00:04:38,150 --> 00:04:41,010 So, in this case, I happen to be working with 91 00:04:41,010 --> 00:04:43,624 a list comprehension that says for every item 92 00:04:43,624 --> 00:04:46,870 in the set of values or the sequence of values 93 00:04:46,870 --> 00:04:49,240 produced by reversed, I would like to 94 00:04:49,240 --> 00:04:51,270 take that item and square it. 95 00:04:51,270 --> 00:04:53,630 So, what we're going to do is walk, in effect, 96 00:04:53,630 --> 00:04:56,640 backwards through this list and put the squares 97 00:04:56,640 --> 00:04:59,690 of those values into the resulting list. 98 00:04:59,690 --> 00:05:02,740 So, in this case I happen to be assigning 99 00:05:02,740 --> 00:05:06,378 that to a variable, so I'll evaluate that variable 100 00:05:06,378 --> 00:05:09,380 and now I can see, in reverse order now, 101 00:05:09,380 --> 00:05:13,350 the square of six is 36, the square of five is 25, 102 00:05:13,350 --> 00:05:16,110 the square of eight is 64, etc. 103 00:05:16,110 --> 00:05:19,420 So, this is different, by the way, 104 00:05:19,420 --> 00:05:24,050 from just having a list and calling it's reverse method, 105 00:05:24,050 --> 00:05:26,228 which is going to modify the original list. 106 00:05:26,228 --> 00:05:28,180 There is a couple of differences. 107 00:05:28,180 --> 00:05:31,755 First of all, not only will this not modify numbers, 108 00:05:31,755 --> 00:05:35,890 but separately, it can be used with any sequence, 109 00:05:35,890 --> 00:05:39,750 not just a list sequence the way 110 00:05:39,750 --> 00:05:42,810 the list method reverse can be used. 111 00:05:42,810 --> 00:05:46,665 Now, there is a super handy function that you will 112 00:05:46,665 --> 00:05:51,665 often encounter in Python applications, it's called Zip. 113 00:05:52,210 --> 00:05:56,832 And it's purpose is to take multiple sequences of values 114 00:05:56,832 --> 00:06:01,832 and combine them into tuples in which the corresponding 115 00:06:03,290 --> 00:06:07,010 elements from every sequence get paired together. 116 00:06:07,010 --> 00:06:09,790 So, for this demonstration, let me go ahead 117 00:06:09,790 --> 00:06:12,540 and create a list called names, 118 00:06:12,540 --> 00:06:15,430 which just contains three string names. 119 00:06:15,430 --> 00:06:19,290 And let's also create a list called grade point averages 120 00:06:19,290 --> 00:06:22,210 that contains three floating point numbers. 121 00:06:22,210 --> 00:06:25,330 So, what I would like to do is quote unquote zip 122 00:06:25,330 --> 00:06:29,300 these two lists together such that we'll have 123 00:06:29,300 --> 00:06:32,934 tuples in which Bob will be paired with 3.5, 124 00:06:32,934 --> 00:06:35,360 Sue will be paired with 4.0, 125 00:06:35,360 --> 00:06:39,030 and Amanda will be paired with 3.5. 126 00:06:39,030 --> 00:06:42,270 This is a common operation when you have 127 00:06:42,270 --> 00:06:44,760 multiple sequences of values that 128 00:06:44,760 --> 00:06:48,830 you need to process together in the same loop. 129 00:06:48,830 --> 00:06:50,670 So with that said, let's actually 130 00:06:50,670 --> 00:06:52,859 create a loop that does just that. 131 00:06:52,859 --> 00:06:55,494 So, let me copy and paste that in here. 132 00:06:55,494 --> 00:06:59,230 So, here we have a loop that is going to be 133 00:06:59,230 --> 00:07:02,580 processing items from tuples 134 00:07:02,580 --> 00:07:05,950 and we're going to actually unpack items 135 00:07:05,950 --> 00:07:08,520 from the result of the in expression here, 136 00:07:08,520 --> 00:07:11,120 into the variables name and gpa. 137 00:07:11,120 --> 00:07:13,530 And for those two variables, we will then display 138 00:07:13,530 --> 00:07:15,480 name equals followed by the name, 139 00:07:15,480 --> 00:07:19,420 a semicolon and gpa equals followed by the gpa. 140 00:07:19,420 --> 00:07:23,220 This is the key new feature that we are demonstrating here. 141 00:07:23,220 --> 00:07:26,240 The zip function, once again, is built into the language 142 00:07:26,240 --> 00:07:30,210 and, once again, it returns an iterator, so it's lazy. 143 00:07:30,210 --> 00:07:32,120 It just gives you back an object 144 00:07:32,120 --> 00:07:34,133 that you can then iterate over. 145 00:07:34,133 --> 00:07:38,030 This particular zip call has two arguments 146 00:07:38,030 --> 00:07:41,343 but it can contain, really, any number of arguments 147 00:07:41,343 --> 00:07:45,790 of parallel sequence type structures that you would 148 00:07:45,790 --> 00:07:48,403 like to zip corresponding elements together from. 149 00:07:48,403 --> 00:07:51,620 So, in this case, names and grade point averages. 150 00:07:51,620 --> 00:07:53,801 And the corresponding tuples will have 151 00:07:53,801 --> 00:07:57,700 the name value followed by the grade point average value 152 00:07:57,700 --> 00:08:01,470 because of the order in which we list the arguments here. 153 00:08:01,470 --> 00:08:05,210 So, what zip will now do, is go through these two sequences 154 00:08:05,210 --> 00:08:09,635 and for each time it's asked to give a new tuple back, 155 00:08:09,635 --> 00:08:12,380 it will grab the corresponding pair of values 156 00:08:12,380 --> 00:08:15,760 from the two sequences, give back that tuple which we, 157 00:08:15,760 --> 00:08:20,430 in this example, are going to then unpack into name and gpa, 158 00:08:20,430 --> 00:08:22,480 and then display the results. 159 00:08:22,480 --> 00:08:24,230 So, let's go ahead and execute that 160 00:08:24,230 --> 00:08:28,838 and you can see Bob and 3.5, Sue and 4.0, 161 00:08:28,838 --> 00:08:33,310 Sue and 4.0, and then Amanda and 3.75. 162 00:08:33,310 --> 00:08:34,620 Now, you may look at that and say 163 00:08:34,620 --> 00:08:36,980 well wait a second, what if the sequences 164 00:08:36,980 --> 00:08:39,470 don't have the same number of elements? 165 00:08:39,470 --> 00:08:43,190 That's okay, zip is smart enough to automatically 166 00:08:43,190 --> 00:08:46,520 stop processing the sequences when it reaches 167 00:08:46,520 --> 00:08:50,143 the end of the shortest sequence that you give it.