7

Say I have two lists:

a=[1,2,3,4,5]
b=[5,4,3,2,1]

I want to create a third one which will be linear sum of two given:

c[i]==a[i]+b[i]
c==[6,6,6,6,6]

Is it possible to do with 'for' constructor? Like:

c = [aa+bb for aa in a for bb in b]

(which obviously returns not what I want)

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
user1513100
  • 191
  • 1
  • 2
  • 12

5 Answers5

25

Use zip():

>>> a = [1,2,3,4,5]
>>> b = [5,4,3,2,1]
>>> c = [x+y for x,y in zip(a, b)]
>>> c
[6, 6, 6, 6, 6]

or:

>>> c = [a[i] + b[i] for i in range(len(a))]
>>> c
[6, 6, 6, 6, 6]

c = [aa+bb for aa in a for bb in b] is something like:

 for aa in a:
     for bb in b:
           aa+bb

this means , select 1 from a and then loop through all elements of b while adding them to 1, and then choose 2 from a and then again loop through all values of b while adding them to 2, that's why you were not getting expected output.

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • Beat me by 15 seconds. +1 and I'll delete mine. – mgilson Jul 09 '12 at 20:58
  • 1
    Should discourage use of `for i in range(len(a))`, using iterators is better practice. – PaulMcG Jul 09 '12 at 21:18
  • 2
    Did some `timeit`, and after testing all the solutions on this site, the fastest was `starmap(add, zip(a, b))`, clocking in at 0.65s. The above solutions were 1.18s and 0.94s respectively. – Joel Cornett Jul 09 '12 at 21:23
6
a=[1,2,3,4,5]
b=[5,4,3,2,1]

[x+y for x,y in zip(a,b)]
[6, 6, 6, 6, 6]

OR

map(lambda x,y:x+y, a, b)
[6, 6, 6, 6, 6]
Joel Cornett
  • 24,192
  • 9
  • 66
  • 88
stilldodge
  • 204
  • 1
  • 2
2
[ay + be for ay, be in zip(a, b)]
Ben
  • 4,980
  • 3
  • 43
  • 84
1
 sums =   [a[i]+b[i] for i in range(len(a))]
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • thanks for the - points ... dunno why this is exactly what he asked for... – Joran Beasley Jul 09 '12 at 20:59
  • It is incorrect. `range()` takes an integer, not a list: http://ideone.com/bnDMC. You should use len(a) instead. – C0deH4cker Jul 09 '12 at 21:00
  • oh yeah your right ... was typing too fast ... fixed ... (but its also covered below in Ashwini Chaudhary's post) – Joran Beasley Jul 09 '12 at 21:00
  • Downvote removed for quick fix. – C0deH4cker Jul 09 '12 at 21:01
  • yeah i feel a bit sheepish for my negative point outrage now... since I was actually wrong in this instance – Joran Beasley Jul 09 '12 at 21:09
  • This is C or VB-style array indexing ported to Python - idiomatic Python iterates over a list using iterators, not the respective array indexes. For instance, this method does not generalize to generator expressions, but the `zip(a,b)` method does. `zip` will also handle the case if a and b are not the same length, but this method assumes they are, or that b is at least as long as a. `for i in range(len(seq)): do_something_with_seq[i]` is far better implemented using `for item in seq: do something with item`. If you absolutely need the index, use `for index,item in enumerate(seq): etc.`. – PaulMcG Jul 09 '12 at 21:17
  • @Paul McGuire: Im not sure I agree with you ... there are plenty of times where it is perfectly acceptable to use `for i in range(10):a[i]` ... of coarse if you could point me to the pep8 style definition that says it should be discouraged I would be more apt to agree with you – Joran Beasley Jul 09 '12 at 21:37
  • @JoranBeasley - you won't find it in PEP8, I look more at the trends in Python in general, towards use of iterators and generators in place of explicit list iterating. I would consider an idiom or interface which supports more types to be better than one that supports fewer. You can't use indexed access for generators, sets, or dicts, but you *can* iterate over them (not germane to this particular problem, in which the iteration order is significant, but still supportive of iterators over indexing). There is no `len` for generators. `range` and `len` require additional function calls. – PaulMcG Jul 09 '12 at 22:17
  • And 99% of the cases where you would use `for i in range(10): a[i]` can be replaced with `for item in a:` or `for i,item in enumerate(a):`. Let's provide good examples of Pythonic usage, instead of hack-ey idioms borrowed from older languages. – PaulMcG Jul 09 '12 at 22:19
  • can you point me to anything that says to try and avoid at all costs? I think that `[a[i]+b[i] for i in range(len(a))]` is more readable than `['item+b[i] for i,item in enumerate(a)]` and _python encourages readability_... however both ways work the same (and probably are on similar CPU time scales) – Joran Beasley Jul 09 '12 at 22:36
-2

I don't know what you're trying to do, but you can easily do what you've asked with numpy. I'm just not sure you really want to add that extra dependency to your code.

darkphoenix
  • 2,147
  • 3
  • 13
  • 14