In [1]:
%load_ext watermark
In [2]:
%watermark -d -v -u
[More information](http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/ipython_magic/watermark.ipynb) about the `watermark` magic command extension.
There is an endless number of possibilities to calculate the difference between successive elements in a Python list. For example, given a list [1,2,3], the difference between successive elements would be [2-1, 3-2] = [1, 1] Below, we will have a look at 4 different alternatives.
We will also be using islice(lst, 1, None)
from the itertools
in-built module instead of a plain lst[1:]
in order to avoid making unnecessary temporary copies of the lists in memory.
In [4]:
from operator import sub
lst = [1,2,3,5]
list(map(sub, lst[1:], lst))
Out[4]:
In [5]:
from itertools import islice
list(map(sub, islice(lst, 1, None), lst))
Out[5]:
In [6]:
[lst[i+1] - lst[i] for i in range(len(lst)-1)]
Out[6]:
In [7]:
[j - i for i, j in zip(lst, islice(lst, 1, None))]
Out[7]:
In [8]:
list(map(lambda x,y: x - y, islice(lst, 1, None), lst))
Out[8]:
In [11]:
import timeit
import random
map_res, map_slice, comp_res, comp_slice, lambda_slice = [], [], [], [], []
orders = [10**i for i in range(4, 8)]
for n in orders:
lst = [random.randint(0, n) for i in range(n)]
print('n=%s (%s of %s)' %(n, orders.index(n)+1, len(orders)))
map_res.append(min(timeit.Timer('list(map(sub, lst[1:], lst))' ,
'from __main__ import lst, sub').repeat(repeat=5, number=1)))
map_slice.append(min(timeit.Timer('list(map(sub, islice(lst, 1, None), lst))' ,
'from __main__ import sub, lst, islice').repeat(repeat=5, number=1)))
comp_res.append(min(timeit.Timer('[lst[i+1] - lst[i] for i in range(len(lst)-1)]' ,
'from __main__ import lst').repeat(repeat=5, number=1)))
comp_slice.append(min(timeit.Timer('[j - i for i, j in zip(lst, islice(lst, 1, None))]' ,
'from __main__ import lst, islice').repeat(repeat=5, number=1)))
lambda_slice.append(min(timeit.Timer('list(map(lambda x,y: x - y, islice(lst, 1, None), lst))' ,
'from __main__ import lst, islice').repeat(repeat=5, number=1)))
print('finished')
In [12]:
%matplotlib inline
In [16]:
from matplotlib import pyplot as plt
def plot():
fig = plt.figure(figsize=(12,6))
plt.plot(orders, map_res,
label='list(map(sub, lst[1:], lst))',
lw=2, alpha=0.6)
plt.plot(orders, map_slice,
label='list(map(sub, islice(lst, 1, None), lst))',
lw=2, alpha=0.6)
plt.plot(orders, comp_res,
label='[lst[i+1] - lst[i] for i in range(len(lst)-1)]',
lw=2, alpha=0.6)
plt.plot(orders, comp_slice,
label='[j - i for i, j in zip(lst, islice(lst, 1, None))]',
linestyle='--', lw=2, alpha=0.6)
plt.plot(orders, lambda_slice,
label='list(map(lambda x,y: x - y, islice(lst, 1, None), lst))',
linestyle='--', lw=2, alpha=0.6)
plt.title('Calculating the difference between successive elements in a Python list', fontsize=20)
plt.xlim([min(orders), max(orders)])
plt.grid()
#plt.xscale('log')
plt.ticklabel_format(style='plain', axis='x')
plt.legend(loc='upper left', fontsize=14)
plt.xlabel('items in the list', fontsize=16)
plt.ylabel('time in seconds', fontsize=16)
plt.tight_layout()
plt.show()
In [17]:
plot()
In [18]:
%watermark -d -v -m