3

I have been searching this for a while, basically I am trying to conditionally increment a list of element by another list, element-wise...

my code is following, but is there a better way to do it? list comprehension, map??

I think a element-wise operator like ~+= from http://www.python.org/dev/peps/pep-0225/ would be really good, but why is it deferred?

for i in range(1,len(s)):
        if s[i]<s[0]:
            s[i]+=p[i]

based on some good feedbacks from you guys I have recoded to the following

i=s<s[0]
s[i]+=p[i]

and s,p are both arrays.

p.s still slow than matlab 5 times for one of my code.

4 Answers 4

2

Here is a quick version:

# sample data
s = [10, 5, 20]
p = [2,2,2]

# As a one-liner.  (You could factor out the lambda)
s = map(lambda (si, pi): si + pi if si < s[0] else si, zip(s,p))

# s is now [10, 7, 20]

This assumes that len(s) <= len(p)

Hope this helps. Let me know. Good luck. :-)

Sign up to request clarification or add additional context in comments.

3 Comments

@jerry Did I answer you question?
@jerry Pure Python will never be as fast as Matlab. Mainly because of the dynamic OO typing. If you need speed, you will need a python module that is designed for arrays. Have a look at: numpy.scipy.org
@jerry If I answered your question, please mark as "answered" and let me know. Thank you. :-)
1

If you don't want to create a new array, then your options are:

  1. What you proposed (though you might want to use xrange depending on the python version)
  2. Use Numpy arrays for s and p. Then you can do something like s[s<s[0]] += p[s<s[0]] if s and p are the same length.
  3. Use Cython to speed up what you've proposed.

2 Comments

hi,justin, just tried numpy, works well, code can be written as i=s<s[0] s[i]+=p[i]
@jerry, yes, you can do that (and should if s is very big).
1

Check this SO question:

Basically, something like:

[sum(a) for a in zip(*[s, p]) if a[0] < 0]

Example:

>>> [sum(a) for a in zip(*[[1, 2, 3], [10, 20, 30]]) if a[0] > 2]
[33]

To clarify, here's what zip does:

>>> zip(*[[1, 2, 3], [4, 5, 6]])
[(1, 4), (2, 5), (3, 6)]

It concatenates two (or more) lists into a list of tuples. You can test for conditions on the elements of each of the tuples.

3 Comments

i know zip, but the problem is generating a new list waste the old list's memory.
also for the condition not true, you get a smaller list and lose the element relative position.
@jerry You are correct on both points, I misread the line where you did the addition. Given that, I don't think there's a better solution than what you proposed.
0
s = [s[i]+p[i]*(s[i]<s[0]) for i in range(1,len(s))]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.