Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

zip list, variables

45 views
Skip to first unread message

flebber

unread,
Nov 20, 2013, 5:06:29 AM11/20/13
to
If

c = map(sum, zip([1, 2, 3], [4, 5, 6]))

c
Out[7]: [5, 7, 9]

why then can't I do this?

a = ([1, 2], [3, 4])

b = ([5, 6], [7, 8])

c = map(sum, zip(a, b))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-cc046c85514b> in <module>()
----> 1 c = map(sum, zip(a, b))

TypeError: unsupported operand type(s) for +: 'int' and 'list'

How can I do this legally?

Sayth

Peter Otten

unread,
Nov 20, 2013, 5:38:36 AM11/20/13
to pytho...@python.org
You are obscuring the issue with your map-zippery. The initial value of
sum() is 0, so if you want to "sum" lists you have to provide a start value,
typically an empty list:

>>> sum([[1],[2]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'list'
>>> sum([[1],[2]], [])
[1, 2]

Applying that to your example:

>>> def list_sum(items):
... return sum(items, [])
...
>>> map(list_sum, zip(a, b))
[[1, 2, 5, 6], [3, 4, 7, 8]]

Alternatively, reduce() does not require an initial value:

>>> map(functools.partial(reduce, operator.add), zip(a, b))
[[1, 2, 5, 6], [3, 4, 7, 8]]

But doing it with a list comprehension is the most pythonic solution here...

Jussi Piitulainen

unread,
Nov 20, 2013, 5:45:58 AM11/20/13
to
The error message comes from sum(([1,2],[5,6])), where start defaults
to 0. A way to understand what is happening is to inspect zip(a,b),
notice that the first element of zip(a,b) is ([1,2],[5,6]), and then
find out what sum(([1,2],[5,6])) is. The extra parentheses may seem a
bit subtle, and at least in Python 3, zip and map return opaque
objects, so it does take a bit to get used to all the details,

The offending operands to '+' are 0 and [1,2].

> How can I do this legally?

I think the easiest is [ x + y for x, y in zip(a,b) ] if you want
concatenation, and something like the following if you want a nested
numerical addition:

>>> [ [ x + y for x, y in zip(x,y) ] for x, y in zip(a,b) ]
[[6, 8], [10, 12]]

There is probably a way to use map and sum for this, together with the
mechanisms that change arguments to lists or vice versa (the syntax
involves *), and partial application to specify a different start for
sum if you want concatenation, but I doubt you can avoid some sort of
nesting in the expression, and I doubt it will be clearer than the
above suggestions. But someone may well show a way. (Sorry if this
paragraph sounds like so much gibberish.)

flebber

unread,
Nov 20, 2013, 3:05:38 PM11/20/13
to
Thank you for the replies.

Looking at the replies I am wondering which solution is more scalable. At the moment it is only 2 nested lists but what about 5, 10, 20 or more?

Should I start looking into numpy to handle this or will list comprehension
>>> [ [ x + y for x, y in zip(x,y) ] for x, y in zip(a,b) ]
Be sufficient ?

Thanks

Sayth

Steven D'Aprano

unread,
Nov 20, 2013, 8:03:39 PM11/20/13
to
Be sufficient for what? You've deleted all context from your post, so I
have no clue what you're talking about.



--
Steven

Peter Otten

unread,
Nov 21, 2013, 3:58:54 AM11/21/13
to pytho...@python.org
I would certainly prefer

>>> a + b
array([[ 6, 8],
[10, 12]])

over the incomprehensible comprehension. But if it is the only usecase for
numpy in your script and you are OK with its current performance, just put
your listcomp into an aptly named function. Then you can write the easily
understandable

c = matrix_add(a, b)

and avoid the numpy dependency.

0 new messages