Python Outerzip/zip最长函数(具有多个填充值)
是否有一个Python函数“outer-zip”,它是的扩展,每个iterable都有不同的默认值Python Outerzip/zip最长函数(具有多个填充值),python,Python,是否有一个Python函数“outer-zip”,它是的扩展,每个iterable都有不同的默认值 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
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)]
我几乎可以使用复制此outerzip函数,但只有None
作为默认值:
注1:内置函数接受任意数量的iterables,因此outerzip
函数也应如此。(例如,人们应该能够计算outerzip((a,0)、(a,0)、(b,1))
类似于zip(a,a,b)
和map(无,a,a,b)
)
注2:我用的样式说“outer-zip”,但这可能不是正确的术语。它的名称(在python-3.x中):
此功能可通过扩展每个输入列表和压缩来定义:
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)]
您可以使用它来支持您的通用iterables用例
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'), '$') )))
我能给a和b换一个不同的填充值吗?@hayden:那怎么行?调用
zip\u longest
w/两个不同的fillvalue
s取决于a
和b
的长度。如果len(a)列表(zip\u longest(a,b,fillvalue=1,如果len(a)>len(b)else 0),您的答案不一致,因为它同时使用了zip\u longest()
和izip\u longest()
…一个人应该能够计算出outerzip(a,0,a,2,b,1)
?这是个好问题!我不确定这是否有意义(我个人认为这不会发生,因为列表的元素总是特定类型的,因此有一个隐含的默认值),但我不确定在一般的outerzip
函数中…使用map
的有用技巧。我想你的问题最好用“zip_longest()“有多个填充值?”因为它被标记为“Python”。@martineau重新命名,保留了这两个值(尽管我想zip_longest是一个更具Python风格的名称!)您使用的nonlocal
使其成为一个仅适用于Python 3的解决方案——尽管Python 2.x版本也可能很容易编写。@martineau:请参阅如何在Python 2中替换nonlocal
。是的,我知道有一些变通方法。事实上,在forizip_longest()
中,一个用于纯Python代码中的计数器
变量,它说这是等效的——这就是为什么我说创建2.x版本可能是一件相对容易的事情。我发表评论是因为OP的问题没有标记为Python-3.x。这个函数非常聪明,值得赏金!回顾过去,有一个小问题是,调用子函数“sentinel”有什么原因吗?@AndyHayden:可能是为了传达它是一个“sentinel值”。
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)]
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'), '$') )))