为什么地图工作像izip_longest,fill = None? [英] Why does map work like izip_longest with fill=None?
问题描述
当 map
具有不同长度的输入时,填充值 None
用于缺少的输入:
>>> x = [[1,2,3,4],[5,6]]
>>>> map(lambda * x:x,* x)
[(1,5),(2,6),(3,无),(4,无)]
这与以下行为相同:
>>> import itertools
>>>>列表(itertools.izip_longest(* x))
[(1,5),(2,6),(3,无),(4,无)]
原因地图
提供了这种行为,而不是以下?
>>> map(lambda * x:x,* x)
/ pre>
[(1,5),(2,6),(3,),(4)]
...有一个简单的方法来获得后一种行为,或者有一些风格的
zip
或map
?解决方案我认为这是核心开发人员选择的设计决策当时他们实现了
map
。对于map
,当它与多个迭代使用时,没有通用定义的行为,引用自 Map(高阶函数):
或者更多的列表在
列表的长度不同时遇到处理问题。各种语言不同一些
引发异常,一些停止在最短列表
的长度之后,忽略其他列表上的额外项目;一些继续到最长列表的
长度,对于已经结束的列表,
将一些占位符值传递给指示没有值的函数。
所以,Python核心开发人员在无作为较短的迭代的占位符1993年向Python发布了hg.python.org/cpython/file/89e1e5d9ccbf/Python/bltinmodule.c#l472rel =nofollow>
映射
但是,在
itertools.imap
的情况下,由于其设计非常灵感,因此可以缩短迭代次数来自标准ML,Haskell和APL等语言。在标准ML和Haskell映射
以最短的迭代结束(我不确定APL虽然)。
Python 3也删除了
映射(None,...)
(或者我们应该说itertools.imap
,Python 3的map
实际上几乎是itertools.imap
: itertools 移动到$ $ / code code code code $ c c $ c> builtins )构造,因为它存在于Python 2中,因为在时间映射
被添加到Python中在Python中没有zip()
函数。
从 Issue2186:
map
和过滤器
不应该支持无
作为第一个参数(仅在Py3k中):
我同意Guido如果
zip()
map(None,...) >已经存在。主要用例已经过时了。
要获得您想要的结果,我建议使用
itertools.izip_longest
与哨兵值(object()
),而不是默认无
,无
如果迭代本身包含无
:从itertools导入izip_longest
def solve(seq):
sentinel = object()
return [tuple(x for x in item if x not sentinel)for $ in
izip_longest(* seq,fillvalue = sentinel)]
print solve( [[1,2,3,4],[5,6]])
#[(1,5),(2,6),(3,),(4)]
When
map
has different-length inputs, a fill value ofNone
is used for the missing inputs:>>> x = [[1,2,3,4],[5,6]] >>> map(lambda *x:x, *x) [(1, 5), (2, 6), (3, None), (4, None)]
This is the same behavior as:
>>> import itertools >>> list(itertools.izip_longest(*x)) [(1, 5), (2, 6), (3, None), (4, None)]
What's the reason
map
provides this behavior, and not the following?>>> map(lambda *x:x, *x) [(1, 5), (2, 6), (3,), (4,)]
…and is there an easy way to get the latter behavior either with some flavor of
zip
ormap
?解决方案I think this a design decision that the core devs opted for at the time they implemented
map
. There's no universally defined behavior formap
when it is used with multiple iterables, quoting from Map (higher-order function):Map with 2 or more lists encounters the issue of handling when the lists are of different lengths. Various languages differ on this; some raise an exception, some stop after the length of the shortest list and ignore extra items on the other lists; some continue on to the length of the longest list, and for the lists that have already ended, pass some placeholder value to the function indicating no value.
So, Python core devs opted for
None
as placeholder for shorter iterables at the timemap
was introduced to Python in 1993.But in case of
itertools.imap
it short-circuits with the shortest iterable because its design is heavily inspired from languages like Standard ML, Haskell and APL. In Standard ML and Haskellmap
ends with shortest iterable(I am not sure about APL though).Python 3 also removed the
map(None, ...)
(or we should sayitertools.imap
, Python 3'smap
is actually almostitertools.imap
: Movemap()
fromitertools
tobuiltins
) construct because it was present in Python 2 only because at the timemap
was added to Python there was nozip()
function in Python.From Issue2186:
map
andfilter
shouldn't supportNone
as first argument (in Py3k only):I concur with Guido that we never would have created
map(None, ...)
ifzip()
had existed. The primary use case is obsolete.
To get the result you want I would suggest using
itertools.izip_longest
with a sentinel value(object()
) rather than defaultNone
,None
will break things if the iterables itself containNone
: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,)]
这篇关于为什么地图工作像izip_longest,fill = None?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!