Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I would like to operate on lists element by element without using numpy, for example, i want add([1,2,3], [2,3,4]) = [3,5,7] and mult([1,1,1],[9,9,9]) = [9,9,9], but i'm not sure which way of doing is it considered 'correct' style.

The two solutions i came up with were

def add(list1,list2):
    list3 = []
    for x in xrange(0,len(list1)):
        list3.append(list1[x]+list2[x])
    return list3

def mult(list1, list2):
    list3 = []
    for x in xrange(0,len(list1)):
        list3.append(list1[x]*list2[x])
    return list3

def div(list1, list2):
    list3 = []
    for x in xrange(0,len(list1)):
        list3.append(list1[x]/list2[x])
    return list3

def sub(list1, list2):
    list3 = []
    for x in xrange(0,len(list1)):
        list3.append(list1[x]-list2[x])
    return list3

where each operator is given a separate function

and

def add(a,b)
    return a+b
def mult(a,b)
    return a*b
def div(a,b)
    return a/b
def sub(a,b)
    return a-b
def elementwiseoperation(list1, list2, function):
    list3 = []
    for x in xrange(0,len(list1)):
        list3.append(function(list1[x],list2[x]))
    return list3

where all the basic functions are defined, and I have a separate function to use them on each element. I skimmed through PEP8, but didn't find anything directly relevant. Which way is better?

share|improve this question
can't you use map? instead of elementwiseoperation. See: docs.python.org/2/library/functions.html#map – Daan Timmer Jul 11 at 14:08

5 Answers

up vote 3 down vote accepted

The normal way to do this would be to use map or itertools.imap:

import operator
multiadd = lambda a,b: map(operator.add, a,b)
print multiadd([1,2,3], [2,3,4]) #=> [3, 5, 7]

Ideone: http://ideone.com/yRLHxW

map is a c-implemented version of your elementwiseoperation, with the advantage of having the standard name, working with any iterable type and being faster.

Alternatively, you could use partial and map for a pleasingly pointfree style:

import operator
import functools

multiadd = functools.partial(map, operator.add)
print multiadd([1,2,3], [2,3,4]) #=> [3, 5, 7]

Ideone: http://ideone.com/BUhRCW

Anyway, you've taken the first steps in functional programming yourself. I suggest you read around the topic.

As a general matter of style, iterating by index using range is generally considered the wrong thing, if you want to visit every item. The usual way of doing this is simply to iterate the structure directly. Use zip or itertools.izip to iterate in parallel:

for x in l:
    print l

for a,b in zip(l,k):
    print a+b

And the usual way to iterate to create a list is not to use append, but a list comprehension:

[a+b for a,b in itertools.izip(l,k)]
share|improve this answer
Thanks for the answers, and the tip about iterating over the list (i've always done it with range for some reason). – user1858363 Jul 11 at 15:07
@user1858363 You're welcome. That's how you'd do it in C or Java; in python it's inefficient and less readable. It's only appropriate when you want to visit some subset of the items. Even then, I'd see if there's an itertools function which could help. – Marcin Jul 11 at 15:40

This could be done with just using map and operator module:

>>> from operator import add,mul
>>> map(add, [1,2,3], [2,3,4])
[3, 5, 7]
>>> map(mul, [1,1,1],[9,9,9])
[9, 9, 9]
share|improve this answer
1  
What's the point of interposing func here? It's literally just an alias for map. – Marcin Jul 11 at 14:13
@Marcin Correct you are, it would be better to remove the func because just map is fine – Ashwini Chaudhary Jul 11 at 14:17
Also, I think you'll be interested in how functools.partial can make this into a reusable function without interposing a lamdba. – Marcin Jul 11 at 14:30
1  
@Marcin Already upvoted your answer. :) – Ashwini Chaudhary Jul 11 at 14:35
;) Still, I hope it appeals to you. I'd actually forgotten it was built-in. – Marcin Jul 11 at 14:37

The second one looks cleaner to me but other than they seem largely the same. Mostly your preference. However your code doesn't do any verification that the lists are the right size, etc.

share|improve this answer
Should be a comment – ElmoVanKielmo Jul 11 at 14:12

You can use zip:

sum = [x+y for x,y in zip (list1, list2) ]
diff = [x-y for x,y in zip (list1, list2) ]
mult = [x*y for x,y in zip (list1, list2) ]
div = [x/y for x,y in zip (list1, list2) ]
share|improve this answer
Map would be cleaner and more efficient for this type of operation. – Marcin Jul 11 at 14:12

How about:

import operator

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

sum = map(operator.add, a, b)
mul = map(operator.mul, a, b)

No, there is no sense in writing own functions in this case.
Just use map and operator as you won't implement anything better.
Any wrapper on map is just another stuff to be put on stack.
Any own implementation is slower than the builtin solution.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.