Starting with list of strings and a list of numbers. Both equal length.
In [ ]:
exlst = ["This", "That", "these", "those", "wit"]
exlsv = [8,10,9,4,20]
Assignment operator allows each item from the list exlst
to be assigned into a variable.
In [ ]:
A,B,C,D,E = exlst
A
But how often are you going to know exactly how many items are in a list when you need to assign to a variable?
For example, this produces an error because the number of variables on the left side of the assignment does not equal the number of items in the list. (Capturing exception with try block to add some clarity.)
In [ ]:
try:
A,B,C,D = exlst
except Exception as X:
print("whoopsie: Exception Type:[{0}] Text:[{1}]".format(type(X),X))
In [ ]:
X, *Y = exlst
In [ ]:
print("X:[ {} ]".format(X))
print("Y:[ {} ]".format(Y))
Ok, can we do this with parameters in a function? Can we pass in a list of many items into a function to perform some operation? First attempt:
In [ ]:
def foo(v1, v2):
print("v1:[ {} ]".format(v1))
print("v2:[ {} ]".format(v2))
In [ ]:
try:
foo(*exlst)
except Exception as X:
print("whoopsie: Exception Type:[{0}] Text:[{1}]".format(type(X),X))
No, the definition of the function requires that there are two and only two parameters.
In [ ]:
def foo(v1, *v2):
print("v1:[ {} ]".format(v1))
print("v2:[ {} ]".format(v2))
In [ ]:
foo(exlst)
Well, that's not quite what I wanted. I wanted the first item from the list in v1
and the remaining items in the list to go into v2
...
In [ ]:
foo(*exlst)
The *
on the parameter function specifies that there will be one or two parameters. The *
on the function call split the list into two parameters -- first and remaining.
In [ ]:
def foo(v1, *v2):
print("v1:[ {} ]".format(v1))
#Exit case. Nothing left in v2 to pass into foo again.
if(len(v2) > 0):
foo(*v2)
In [ ]:
foo(*exlst)
In [ ]:
exlst = ["This", "That", "these", "those", "wit"]
exlsv = [8,10,9,4,20]
What I have are two collections exlst
and exlsv
.
What I want is one collection where the first element of exlst
is paired with the first element of exlsv
This is where zip
comes in. https://docs.python.org/3/library/functions.html#zip
In [ ]:
zip(exlst,exlsv)
Huh? Oh, it's not performing the operation immediately. zip
is returning an iterator which is an object that will step through and provide the results when iterated with next
.
In [ ]:
zf = zip(exlst,exlsv)
NOTE iterating over a zip consumes the zip. The first time we ask for a list from a zip. It returns zipped results, however subsequent calls will return no results.
In [ ]:
next(zf)
In [ ]:
next(zf)
In [ ]:
list(zf)
so you have to be careful with iterators that you don't use them up before you expect to. You could create a copy, but that forces all the calculation over the list to happen at once... which could be a problem if it's an infinite collection. :o
In [ ]:
zflc = list(zip(exlst,exlsv)).copy()
zflc
Now zflc
is a fully realized list of tuples where each tuple is the corresponding values from exlst
and exlsv
.
In [ ]:
#returns an iterator zipping up two collections
zf = zip(exlst,exlsv)
#returns lists unzipping a collection into result collections
c1,c2 = zip(*zf)
In [ ]:
c1
In [ ]:
c2