I write a program to weave lists of floats together, for example:
l1 = [5.4, 4.5, 8.7]
l2 = [6.5, 7.8]
l3 = [6.7, 6.9]
I want to weave l1 into
Another solution (based on Martijn Pieters code) which avoids recursion is:
try:
from itertools import zip_longest
except ImportError:
# Python 2
from itertools import izip_longest as zip_longest
def weave_two(row1, row2):
return [v for v in sum(zip_longest(row1, row2, fillvalue=None), ()) if v is not None]
def weave_rows(*args):
if len(args) < 2:
return None
current = weave_two(args[0], args[1])
for i in range(2, len(args)):
current = weave_two(current, args[i])
return current
usage:
>>> weave_rows(l1, l2, l3)
[5.4, 6.7, 6.5, 6.9, 4.5, 7.8, 8.7]
OK, as peoples comments, this seems a strange case to start using classes but something like this should work:
from itertools import zip_longest
class Weaver():
def __init__(self,data):
self.result = data
def weave(data):
self.result = sum(zip_longest(self.result, data),()) # or whatever version
# works best from
# the other answers
w = Weaver(l1)
w.weave(l2)
w.weave(l3)
print(w.result)
This creates a Weaver
object w
and initialises it with l1
. Then you weave the other lists in one by one and it stores the result internally and finally you access and print that result.
Your weave function drops the last element of l2
; you need to use itertools.zip_longest() here:
try:
from itertools import zip_longest
except ImportError:
# Python 2
from itertools import izip_longest as zip_longest
def weave_rows(row1, row2):
return [v for v in sum(zip_longest(row1, row2), ()) if v is not None]
Note that you need to return, not print, your output. The izip_longest()
call adds None
placeholders, which we need to remove again from the sum()
output after zipping.
Now you can simply weave in a 3rd list into the output of the previous two:
weave(weave(l1, l2), l3)
Demo:
>>> weave_rows(l1, l2)
[5.4, 6.5, 4.5, 7.8, 8.7]
>>> weave_rows(weave_rows(l1, l2), l3)
[5.4, 6.7, 6.5, 6.9, 4.5, 7.8, 8.7]
Function you wrote returns None
, as no return statement is present. Replace print
with return
and chain calls. You might also need izip_longest
instead of zip for lists of nonequal size:
With izip_longest:
from itertools import izip_longest
def weave(l1, l2):
return filter(None, sum(izip_longest(l1, l2), ())
demo
>>> weave(weave(l1, l2), l3)
(5.4, 6.7, 6.5, 6.9, 4.5, 7.8, 8.7)
Without, zip breaks on shortest argument:
>>> def weave_shortest(l1, l2):
return sum(zip(l1, l2), ())
>>> weave_shortest(l3, weave_shortest(l1, l2))
(5.4, 6.7, 6.5, 6.9)