I have two lists combined sequentially to create a nested list with python's map and zip funcionality; however, I wish to recreate this with itertools.
Furthermore, I am trying to understand why itertools.chain is returning a flattened list when I insert two lists, but when I add a nested list it simply returns the nested list.
Any help on these two issues would be greatly appreciated.
from itertools import chain
a = [0,1,2,3]
b = [4,5,6,7]
#how can I produce this with itertools?
c = list(map(list, zip(a,b)))
print(c) #[[0, 4], [1, 5], [2, 6], [3, 7]]
d = list(chain(c))
print(d) #[[0, 4], [1, 5], [2, 6], [3, 7]]
d = list(chain(a,b))
print(d) #[0, 1, 2, 3, 4, 5, 6, 7]
I'll try to answer your questions as best I can.
First off, itertools.chain
doesn't work the way you think it does. chain
takes x
number of iterables and iterates over them in sequence. When you call chain
, it essentially (internally) packs the objects into a list:
chain("ABC", "DEF") # Internally creates ["ABC", "DEF"]
Inside the method, it accesses each of these items one at a time, and iterates through them:
for iter_item in arguments:
for item in iter_item:
yield item
So when you call chain([[a,b],[c,d,e],[f,g]])
, it creates a list with one iterable object: the list you passed as an argument. So now it looks like this:
[ #outer
[ #inner
[a,b],
[c,d,e],
[f,g]
]
]
chain
as such iterates over the inner list, and returns three elements: [a,b]
, [c,d,e]
, and [f,g]
in order. Then they get repacked by list
, giving you what you had in the first place.
Incidentally, there is a way to do what you want to: chain.from_iterable
. This is an alternate constructor for chain
which accepts a single iterable, such as your list, and pulls the elements out to iterate over. So instead of this:
# chain(l)
[ #outer
[ #inner
[a,b],
[c,d,e],
[f,g]
]
]
You get this:
# chain.from_iterable(l)
[
[a,b],
[c,d,e],
[f,g]
]
This will iterate through the three sub-lists, and return them in one sequence, so list(chain.from_iterable(l))
will return [a,b,c,d,e,f,g]
.
As for your second question: While I don't know why itertools
is a necessity to this process, you can do this in Python 2.x:
list(itertools.izip(x,y))
However, in 3.x, the izip
function has been removed. There is still zip_longest
, which will match up as many pairs as it can, and accept a filler value for extra pairs: list(zip_longest([a,b,c],[d,e,f,g,h],fillvalue="N"))
returns [(a,d),(b,e),(c,f),(N,g),(N,h)]
since the second list is longer than the first. Normal zip
will take the shortest iterable and cut off the rest.
In other words, unless you want zip_longest
instead of zip
, itertools
does not have a built-in method for zipping.
You can also run itertools.chain(*your_list_of_lists)
. For example:
for p in itertools.chain(*[[1,2],[3,4]]):
print(p)
1
2
3
4
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.