1

In lisp I used to do things like that, knowing it won't crash:

 [3]> (mapcar #'+ '(1 2 3) '(1 2))
(2 4)

The equivalent in python seems to crash:

>>> 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'

Is there a function in python that works like the lisp version on not-equal length lists? Or, is there a way to change the behavior of map?

elyashiv
  • 3,623
  • 2
  • 29
  • 52

1 Answers1

5

This problem is suitable for Python 2.x (thanks to @user2357112). The documentation for map in Python 3.x says:

The iterator stops when the shortest input iterable is exhausted.

So, in Python 3.x you could just use map:

In [1]: list(map(lambda a, b: a + b, [1, 2, 3], [1, 2]))
Out[1]: [2, 4]

But the documentation for map in Python 2.x says:

If one iterable is shorter than another it is assumed to be extended with None items.

So, you should firstly zip these lists:

In [2]: map(sum, zip([1, 2, 3], [1, 2]))
Out[2]: [2, 4]

Because zip will truncate returned list to the length of the shortest argument sequence (as said in documentation)

You could also define your own function zip_with (example from this answer):

import itertools

def zip_with(f, *coll):
    return itertools.starmap(f, itertools.izip(*coll))

Example of usage:

In [3]: list(zip_with(operator.add, [1, 2, 3], [1, 2]))
Out[3]: [2, 4]
Community
  • 1
  • 1
awesoon
  • 32,469
  • 11
  • 74
  • 99
  • 1
    Note that the argument unpacking in `lambda (x, y): x + y` doesn't work in Python 3. [It messed with introspection and wasn't used much.](http://legacy.python.org/dev/peps/pep-3113/) That makes the transformation a bit messier in Python 3. Fortunately, Python 3's `map` already does what you want. – user2357112 Jul 10 '14 at 09:34
  • 1
    The documentation you're linking is for the Python 3 version of `map`, where none of this is necessary. – user2357112 Jul 10 '14 at 09:39