L = [2, 5, 8, 3, 9, 1]
I want to generate a list containing the differences between adjacent
elements, i.e.,
Ld = [3, 3, -5, 6, -8]
I don't see how I can do this (easily/elegantly) with list
comprehensions.
Any suggestions? Thanks!
[j - i for i, j in zip(L, L[1:])]
--
Cliff Wells, Software Engineer
Logiplex Corporation (www.logiplex.net)
(503) 978-6726 x308 (800) 735-0555 x308
def adjacentdiffs(seq):
return [ x - y for x, y in zip (seq[1:], seq[:-1]) ]
Sean
"Phil Schmidt" <psch...@omnimn.com> wrote in message
news:69413f9.03032...@posting.google.com...
>>> [L[i+1]-L[i] for i in xrange(len(L)-1)]
[3, 3, -5, 6, -8]
>>>
Depends on your definitions of "easily" and "elegantly" :-)
I see you've already received two excellent suggestions based on
zip, so here's the alternative based on indices instead:
[ L[i+1]-L[i] for i in range(len(L)-1) ]
Alex
Numeric provides the simplest possible way of writing this:
In [1]: L = array([2, 5, 8, 3, 9, 1])
In [2]: L[1:]-L[:-1]
Out[2]: array([ 3, 3, -5, 6, -8])
Note that in the above, the data is NOT copied when you do L[1:], so even if L
is a multi-megabyte array, you won't incurr a copy penalty. The semantics of
Numeric slicing is different from that of python lists, for very good reasons.
And the loop is done in C, so it's extremely fast.
Cheers,
f.
While that works, I think it obfuscates what's being
done rather more than necessary.
I would suggest:
[seq[i+1] - seq[i] for i in xrange(len(seq) - 1)]
It's a bit more efficient to boot, since it avoids
constructing an intermediate list of tuples.
--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg
True.
And,
import operator
map(operator.sub, seq[1:], seq[:-1])
suffers from the same inefficiency, but it is faster ;)
Sean
First, define a "window" iterator (useful for many other things in
addition to this):
def window(L, size):
for i in xrange(len(L) - size + 1):
yield L[i:i+size]
The it's simple:
[y - x for (x, y) in window(L, 2)]
Jeremy
No reason not to give timeit.py a try when discussing speed...:
[alex@lancelot alex]$ python timeit.py -s 'import operator' -s
'seq=range(1000)' 'x=map(operator.sub, seq[1:], seq[:-1])'
1000 loops, best of 3: 919 usec per loop
[alex@lancelot alex]$ python timeit.py -s 'import operator' -s
'seq=range(1000)' 'x=[seq[i+1]-seq[i] for i in xrange(len(seq)-1)]'
1000 loops, best of 3: 1.96e+03 usec per loop
[alex@lancelot alex]$ python timeit.py -s 'import operator' -s
'seq=range(1000)' 'x=map(lambda a, b: a-b, seq[1:], seq[:-1])'
1000 loops, best of 3: 1.69e+03 usec per loop
[alex@lancelot alex]$ python timeit.py -s 'import operator' -s
'seq=range(1000)' 'x=[a-b for a,b in zip(seq[1:],seq)]'
100 loops, best of 3: 1.78e+03 usec per loop
so, yes: map is way faster when you can pass it a builtin
function from operator (not so much when you need a lambda,
though). And zip turns out to be a little bit faster (on
this machine) than the xrange-based solution.
One result that surprises me a lot...:
[alex@lancelot alex]$ python timeit.py -s 'import operator' -s
'seq=range(1000)' 'x=map(int.__sub__, seq[1:], seq[:-1])'
1000 loops, best of 3: 1.68e+03 usec per loop
I have no idea how or why operator.sub can be faster
than int.__sub__ in this case...!
Alex
Perhaps because int.__sub__ returns a wrapper object
around the underlying function, whereas operator.sub
provides more direct access to it? Not sure about
that.
> Alex Martelli wrote:
> > I have no idea how or why operator.sub can be faster
> > than int.__sub__ in this case...!
>
> Perhaps because int.__sub__ returns a wrapper object
> around the underlying function, whereas operator.sub
> provides more direct access to it? Not sure about
> that.
Yeah, that's what I was thinking too. ceval.c knows how to call
PyCFunction objects directly, but I guess __int__.__sub__ goes through
the whole tp_call thing. The latter may also do more type checking;
not sure about that.
Cheers,
M.
--
Do I do everything in C++ and teach a course in advanced swearing?
-- David Beazley at IPC8, on choosing a language for teaching
Hi.
How about this?
If, say, L1 = [a1, a2, a3], L2 = [b1, b2, b3, b4, b5], then
zip(L1, L2) = [(a1,b1), (a2,b2), (a3, b3)]. Hence,
[a - b for (a,b) in zip(L1, L2)] = [a1-b1, a2-b2, a3-b3]
This solves your problem if you set L1 = L, L2 = L[1:]. That is,
Ld = [a - b for (a,b) in zip(L[1:], L)]
print 'Ld: ', Ld
>> Ld: [3, 3, -5, 6, -8]
Cheers.