Python函数是否为“outer-zip”,它是zip
的扩展名,每个可迭代的默认值都不同?
a = [1, 2, 3] # associate a default value 0
b = [4, 5, 6, 7] # associate b default value 1
zip(a,b) # [(1, 4), (2, 5), (3, 6)]
outerzip((a, 0), (b, 1)) = [(1, 4), (2, 5), (3, 6), (0, 7)]
outerzip((b, 0), (a, 1)) = [(4, 1), (5, 2), (6, 3), (7, 1)]
我几乎可以使用map复制此外部函数,但None
仅作为 默认值:
map(None, a, b) # [(1, 4), (2, 5), (3, 6), (None, 7)]
注1:内置zip
函数需要任意数量的迭代,因此outerzip
函数也应如此。 (例如,一个人应该能够像outerzip((a,0),(a,0),(b,1))
和zip(a,a,b)
一样计算map(None, a, a, b)
。)
注意2:我用this haskell question的风格说“outer-zip”,但这可能不是正确的术语。
答案 0 :(得分:7)
在python-3.x中称为izip_longest
(zip_longest
):
>>> from itertools import izip_longest
>>> a = [1,2,3]
>>> b = [4,5,6,7]
>>> list(zip_longest(a, b, fillvalue=0))
[(1, 4), (2, 5), (3, 6), (0, 7)]
答案 1 :(得分:3)
您可以modify zip_longest
支持一般迭代的用例。
from itertools import chain, repeat
class OuterZipStopIteration(Exception):
pass
def outer_zip(*args):
count = len(args) - 1
def sentinel(default):
nonlocal count
if not count:
raise OuterZipStopIteration
count -= 1
yield default
iters = [chain(p, sentinel(default), repeat(default)) for p, default in args]
try:
while iters:
yield tuple(map(next, iters))
except OuterZipStopIteration:
pass
print(list(outer_zip( ("abcd", '!'),
("ef", '@'),
(map(int, '345'), '$') )))
答案 2 :(得分:1)
可以通过扩展每个输入的列表和压缩来定义此功能:
def outerzip(*args):
# args = (a, default_a), (b, default_b), ...
max_length = max( map( lambda s: len(s[0]), args))
extended_args = [ s[0] + [s[1]]*(max_length-len(s[0])) for s in args ]
return zip(*extended_args)
outerzip((a, 0), (b, 1)) # [(1, 4), (2, 5), (3, 6), (0, 7)]