当map
具有不同长度的输入时,填充值None
将用于缺少的输入:
>>> x = [[1,2,3,4],[5,6]]
>>> map(lambda *x:x, *x)
[(1, 5), (2, 6), (3, None), (4, None)]
这与以下行为相同:
>>> import itertools
>>> list(itertools.izip_longest(*x))
[(1, 5), (2, 6), (3, None), (4, None)]
map
提供此行为的原因是什么,而不是以下内容?
>>> map(lambda *x:x, *x)
[(1, 5), (2, 6), (3,), (4,)]
...是否有一种简单的方法可以使用zip
或map
的某种风格来获得后一种行为?
答案 0 :(得分:5)
我认为这是核心开发人员在实施map
时选择的设计决策。当map
与多个可迭代项一起使用时,Map (higher-order function)引用时没有普遍定义的行为:
使用2个或更多列表的地图遇到处理时的问题 列表有不同的长度。各种语言不同;一些 引发异常,有些在最短列表的长度后停止 并忽略其他列表中的额外项目;一些继续到 最长列表的长度,以及已经结束的列表, 将一些占位符值传递给函数,表示没有值。
因此,Python核心开发人员选择None
作为占位符,以便在1993年map
was introduced向Python提供更短的迭代次数。
但是在itertools.imap
的情况下,它以最短的可迭代次数进行短路,因为它的设计受到了标准ML,Haskell和APL等语言的极大启发。在标准ML和Haskell中map
以最短的可迭代结束(虽然我不确定APL)。
Python 3还删除了map(None, ...)
(或者我们应该说itertools.imap
,Python 3' map
实际上几乎是itertools.imap
:Move map()
from itertools
to builtins
)构造因为它只存在于Python 2中,因为当时map
被添加到Python中,Python中没有zip()
函数。
来自Issue2186: map
and filter
shouldn't support None
as first argument (in Py3k only):
我同意Guido的意见,如果我们永远不会创建
map(None, ...)
zip()
已经存在。主要用例已过时。
要获得您想要的结果,我建议您使用带有标记值(itertools.izip_longest
)的object()
而不是默认None
,None
如果迭代本身会破坏事物包含None
:
from itertools import izip_longest
def solve(seq):
sentinel = object()
return [tuple(x for x in item if x is not sentinel) for item in
izip_longest(*seq, fillvalue=sentinel)]
print solve([[1,2,3,4],[5,6]])
# [(1, 5), (2, 6), (3,), (4,)]
答案 1 :(得分:1)
鉴于第一个列表总是更长,而且只有两个列表,你可以这样做:
x = [1,2,3,4,5]
y = ['a','b']
zip(x,y) + [(i,) for i in x[len(y):]]
[(1, 'a'), (2, 'b'), (3,), (4,), (5,)]