在长度不等的列表上使用Python的map
在Lisp语言中,我以前常常这样做,因为我知道这样不会出错:
[3]> (mapcar #'+ '(1 2 3) '(1 2))
(2 4)
在Python中,做同样的事情似乎会出错:
>>> map(lambda x,y : x + y, [1,2,3], [1,2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
在Python中有没有一个函数,能像Lisp那样处理长度不一样的列表?或者,有没有办法改变map的行为?
1 个回答
5
这个问题适合用 Python 2.x 来解决(感谢 @user2357112)。在 Python 3.x 的文档中,关于 map
的说明是:
当最短的输入可迭代对象用完时,迭代器就会停止。
所以,在 Python 3.x 中,你可以直接使用 map
:
In [1]: list(map(lambda a, b: a + b, [1, 2, 3], [1, 2]))
Out[1]: [2, 4]
但是在 Python 2.x 的文档中,关于 map
的说明是:
如果一个可迭代对象比另一个短,它会被假设用 None 项目来扩展。
所以,你应该先用 zip
把这些列表组合起来:
In [2]: map(sum, zip([1, 2, 3], [1, 2]))
Out[2]: [2, 4]
因为 zip
会把返回的列表截断到最短的参数序列的长度(正如文档中所说的那样)。
你也可以定义自己的函数 zip_with
(这个答案中的例子):
import itertools
def zip_with(f, *coll):
return itertools.starmap(f, itertools.izip(*coll))
使用示例:
In [3]: list(zip_with(operator.add, [1, 2, 3], [1, 2]))
Out[3]: [2, 4]