In [1]:
%load_ext watermark

In [2]:
%watermark -d -v -u

Last updated: 23/07/2014

CPython 3.4.1
IPython 2.0.0


[More information](http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/ipython_magic/watermark.ipynb) about the watermark magic command extension.

I would be happy to hear your comments and suggestions.
Please feel free to drop me a note via twitter, email, or google+.

# Day 20 - One Python Benchmark per Day¶

## Calculating the difference between successive elements in a Python list¶

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]:
[1, 1, 2]
In [5]:
from itertools import islice

list(map(sub, islice(lst, 1, None), lst))

Out[5]:
[1, 1, 2]
In [6]:
[lst[i+1] - lst[i] for i in range(len(lst)-1)]

Out[6]:
[1, 1, 2]
In [7]:
[j - i for i, j in zip(lst, islice(lst, 1, None))]

Out[7]:
[1, 1, 2]
In [8]:
list(map(lambda x,y: x - y, islice(lst, 1, None), lst))

Out[8]:
[1, 1, 2]

# Bechmarking via timeit¶

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')

n=10000 (1 of 4)
n=100000 (2 of 4)
n=1000000 (3 of 4)
n=10000000 (4 of 4)
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()


# Results¶

In [17]:
plot()

In [18]:
%watermark -d -v -m

23/07/2014

CPython 3.4.1
IPython 2.0.0

compiler   : GCC 4.2.1 (Apple Inc. build 5577)
system     : Darwin
release    : 13.2.0
machine    : x86_64
processor  : i386
CPU cores  : 4
interpreter: 64bit