python calculating intervals using foldleft using lambda
Question
def tointervals(tlist):
count=0
for i in tlist:
if count == 0:
count = count + 1
yield 0
else:
count = count + 1
yield i - tlist[count -2]
I test it like so:
In [272]: list(tointervals([1,2,3,4,10]))
Out[272]: [0, 1, 1, 1, 6]
Great, that's exactly what I was looking for
But I want to do it in a more functional way (I'm mostly using Scala)
I'm terminally confused about this, mainly due to unfamiliarity with Python. The closest I've gotten before giving up in terminal confusion is this.
In [292]: reduce(lambda x,y: (x[0] + [y - x[0][x[1]] ],x[1]+1), [1,2,3,4,10], ([0],0))
Out[292]: ([0, 1, 1, 2, 2, 8], 5)
Which is obviously wrong, but that's the direction I was trying... Am I being foolish, trying to use reduce, or can I just not code for toffee? Be gentle, please.
Solution
A list comprehension will be more pythonic:
>>> l = [1, 2, 3, 4, 10]
>>> [y-x for x, y in zip(l, l[1:])]
[1, 1, 1, 6]
OTHER TIPS
This is the Pythonic way, if I understand correctly what your intention is:
def tointervals(l):
return [0] + [l[i] - l[i-1] for i in xrange(1, len(l))]
or
def tointervals(l):
return (y-x for x,y in itertools.izip([l[0]] + l[:-1], l))
Functional programming is not considered a goal per se in the Python community and language support for it is limited -- "practicality beats purity".
I'd rather go with one of more pythonic solutions from this thread, but if you want to see the reduce
-based solution just for fun, it would be something like that:
reduce(lambda x,y: (x[0] + [y-x[1]], y), [1,2,3,4,10], ([], 0))
Please do not try that in real-life code because your colleagues will curse you.
Building on larsmans' answer, you could also make a generator like you do in your procedural code:
def tointervals(xs):
return itertools.chain((0,), (xs[i] - xs[i-1] for i in range(1, len(xs))))
Note: use xrange
with python2.