tags:

views:

65

answers:

5

I have a list of numbers, say

data = [45,34,33,20,16,13,12,3]

I'd like to compute the difference between 2 and 2 items, (that is, for the above data I want to compute 45-34,33-20,16-13 and 12-3, what's the python way of doing that ?

Also, more generally, how should I apply a function to 2 and 2 of these elements, that is, I want to call myfunc(data[0],data[1]),myfunc(data[2],data[3]) and so on over the list.

+2  A: 

You could create your own iterator to iterate over the elements two-by-two:

class myiter(object):
    def __iter__(self):
        return self
    def next(self):
        a = self.l.next()
        b = self.l.next()
        return (a, b)
    def __init__(self, l):
        self.l = iter(l)

The iterator returns tuples of two elements at a time:

>>> for x, y in i(data):
...     print x, y
45 34
33 20
16 13
12 3

Then you can use it to map your function:

>>> [myfunc(x, y) for x, y in myiter(data)]
Ivo
+1 for elegance..
Srinivas Reddy Thatiparthy
+1  A: 
from itertools import tee,izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

for a,b in pairwise(data):
    print a-b

Requires Python 2.6 or later. I took pairwise() from here.

loevborg
OP doesn't want `pairwise`, but `grouper`.
KennyTM
Nice as code, though different function as has overlapping pairs.
Tony Veijalainen
Kenny, you're absolutely right.
loevborg
+5  A: 

Try slicing the list:

from itertools import izip
[myfunc(a, b) for a, b in izip(data[::2], data[1::2])]

or you can use the fact that izip guarantees the order in which it consumes its arguments:

idata = iter(data)
[myfunc(a, b) for a, b in izip(idata, idata)]
Duncan
+2  A: 
def pairs(iterable):
    while iterable:
        yield next(iterable),next(iterable)

data = [45,34,33,20,16,13,12,3]
print "With pairs generator"
print ','.join(str(a-b) for a,b in pairs(iter(data)))

Consuming version (data will be removed from the list, so take copy if still needed), "without comprehension".

print 'By simple list pop way'
data_c = data[:]
result=[]
while data_c: result.append(data_c.pop(0)-data_c.pop(0))
print result

I would use generally list comprehensions and slicing, but these solutions are maybe sometimes more understandable.

Tony Veijalainen
+1  A: 
diffs = [data[i] - data[i+1] for i in range(0, len(data), 2)]

or the general case

pairs = [(data[i], data[i+1]) for i in range(0, len(data), 2)]
results = [myfunc(*p) for p in pairs]

Not as elegant as some of the other solutions maybe. Still this ought to be mentioned.

jellybean