- [Narrator] In this video, we'd like to present
some additional functions that are
capable of processing sequences of elements.
We'll use lists for demonstration purposes,
but any sequence can be processed by the functions
that I'm about to demonstrate to you.
And part of what I'd like to do here
is revisit the min and max functions,
which by the way are also reductions in
functional style programming because they look at
a sequence of elements and give you back one result,
the minimum or the maximum respectively.
Now, in each of those functions cases,
the default way that they work is to
compare objects in their default manner.
So, if we're talking about integers,
it's going to look at two integers
and the smaller one is going to be the minimum
or the larger one is going to be the maximum.
On the other hand, if I'm looking at strings,
smaller and larger depends on the underlying
character codes of the characters within those strings.
So for example, if I go ahead and compare Red
to the string orange with a lowercase "o",
clearly orange comes before red alphabetically
but numerically, capital "R" comes before lowercase "o"
in the underlying character set,
which is the default way in which strings
are going to be compared in Python.
So, I get true here because capital "R"
is less than lowercase "o" and we can confirm that,
by the way, with a function called ord,
that's built into the language,
which gives you back, for a given character,
the underlying numeric code in the Unicode character set.
So, the ordinal value of the character "R" is 82
and if I recall that and put an "o" in there,
you can see that lowercase "o" is 111.
So, indeed, this is true because 82 is less than 111.
Now, what I'd like to do in this example to start out,
is put in a list of strings with various
upper and lowercase strings in it,
and I want to demonstrate the min and max functions
once again, this time providing a second argument
that says how to compare the items.
So, min is capable of receiving a sequence of values
and giving you the smallest element in that sequence.
But if you supply the key, keyword argument,
in this case we're providing it as a lambda expression,
but it could be some function that returns a value.
What's going to happen is it will use this lambda expression
to help compare the elements in the sequence.
So, here the lambda is going to take
each string that we give it and give us back
the lowercase only version of that string.
So, even though I have upper and lowercase letters
in the strings in the original collection,
it's going to process red with a lowercase "r",
yellow with a lowercase "y", and b with a lowercase "b".
And then, based on that, we'll figure out
the smallest item in the collection,
which is blue alphabetically as opposed to numerically.
It's still comparing them numerically
but now that all the letters are lowercase,
it's able to give me the alphabetic ordering
that I'm looking for in this particular example.
And similarly, I can go ahead and calculate the max.
So again, based on these strings here,
if we convert them all to lowercase letters first,
then we can figure out alphabetically
which is the largest string,
which in this case is the string yellow.
Now, there are a couple of other sequence processing
functions that could come in handy in a number of scenarios,
so I just wanted to introduce those to you as well.
So, first let me go ahead and create a list called numbers
for the next piece of this demonstration.
In this demonstration, I'd like to
demonstrate the reversed function,
which takes as it's argument a sequence
and gives you back a new sequence in reverse order.
So, let me paste in a statement here for us to look at.
Here is the reverse call that I'm introducing.
Now, reversed like filter and map
is going to give you back an iterator.
So again, this is a lazy function,
it does nothing until you iterate over it's results.
So, it does nothing other than create the iterator,
I should say, until you iterate over those results.
So, in this case, I happen to be working with
a list comprehension that says for every item
in the set of values or the sequence of values
produced by reversed, I would like to
take that item and square it.
So, what we're going to do is walk, in effect,
backwards through this list and put the squares
of those values into the resulting list.
So, in this case I happen to be assigning
that to a variable, so I'll evaluate that variable
and now I can see, in reverse order now,
the square of six is 36, the square of five is 25,
the square of eight is 64, etc.
So, this is different, by the way,
from just having a list and calling it's reverse method,
which is going to modify the original list.
There is a couple of differences.
First of all, not only will this not modify numbers,
but separately, it can be used with any sequence,
not just a list sequence the way
the list method reverse can be used.
Now, there is a super handy function that you will
often encounter in Python applications, it's called Zip.
And it's purpose is to take multiple sequences of values
and combine them into tuples in which the corresponding
elements from every sequence get paired together.
So, for this demonstration, let me go ahead
and create a list called names,
which just contains three string names.
And let's also create a list called grade point averages
that contains three floating point numbers.
So, what I would like to do is quote unquote zip
these two lists together such that we'll have
tuples in which Bob will be paired with 3.5,
Sue will be paired with 4.0,
and Amanda will be paired with 3.5.
This is a common operation when you have
multiple sequences of values that
you need to process together in the same loop.
So with that said, let's actually
create a loop that does just that.
So, let me copy and paste that in here.
So, here we have a loop that is going to be
processing items from tuples
and we're going to actually unpack items
from the result of the in expression here,
into the variables name and gpa.
And for those two variables, we will then display
name equals followed by the name,
a semicolon and gpa equals followed by the gpa.
This is the key new feature that we are demonstrating here.
The zip function, once again, is built into the language
and, once again, it returns an iterator, so it's lazy.
It just gives you back an object
that you can then iterate over.
This particular zip call has two arguments
but it can contain, really, any number of arguments
of parallel sequence type structures that you would
like to zip corresponding elements together from.
So, in this case, names and grade point averages.
And the corresponding tuples will have
the name value followed by the grade point average value
because of the order in which we list the arguments here.
So, what zip will now do, is go through these two sequences
and for each time it's asked to give a new tuple back,
it will grab the corresponding pair of values
from the two sequences, give back that tuple which we,
in this example, are going to then unpack into name and gpa,
and then display the results.
So, let's go ahead and execute that
and you can see Bob and 3.5, Sue and 4.0,
Sue and 4.0, and then Amanda and 3.75.
Now, you may look at that and say
well wait a second, what if the sequences
don't have the same number of elements?
That's okay, zip is smart enough to automatically
stop processing the sequences when it reaches
the end of the shortest sequence that you give it.