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