sequence - Python: find out whether a list of integers is coherent -


i trying find out whether list of integers coherent or 'at 1 stretch', meaning difference between 2 neighboring elements must 1 , numbers must increasing monotonically. found neat approach can group number in list minus position of element in list -- difference changes when numbers not coherent. obviously, there should 1 group when sequence not contain gaps or repetitions.

test:

>>> l1 = [1, 2, 3, 4, 5, 6] >>> l2 = [1, 2, 3, 4, 5, 7] >>> l3 = [1, 2, 3, 4, 5, 5] >>> l4 = [1, 2, 3, 4, 5, 4] >>> l5 = [6, 5, 4, 3, 2, 1] >>> def is_coherent(seq): ...     return len(list(g _, g in itertools.groupby(enumerate(seq), lambda (i,e): i-e))) == 1 ...  >>> is_coherent(l1) true >>> is_coherent(l2) false >>> is_coherent(l3) false >>> is_coherent(l4) false >>> is_coherent(l5) false 

it works well, find solution bit convoluted in view of simplicity of problem. can come clearer way achieve same without increasing code length?

edit: summary of answers

from answers given below, solution

def is_coherent(seq):     return seq == range(seq[0], seq[-1]+1) 

clearly wins. small lists (10^3 elements), on order of 10 times faster groupby approach , (on machine) still 4 times faster next best approach (using izip_longest). has worst scaling behavior, large list 10^8 elements still 2 times faster next best approach, again izip_longest-based solution.

relevant timing information obtained timeit:

testing is_coherent_groupby...    small/large/larger/verylarge duration: 8.27 s, 20.23 s, 20.22 s, 20.76 s    largest/smallest = 2.51 testing is_coherent_npdiff...    small/large/larger/verylarge duration: 7.05 s, 15.81 s, 16.16 s, 15.94 s    largest/smallest = 2.26 testing is_coherent_zip...    small/large/larger/verylarge duration: 5.74 s, 20.54 s, 21.69 s, 24.62 s    largest/smallest = 4.28 testing is_coherent_izip_longest...    small/large/larger/verylarge duration: 4.20 s, 10.81 s, 10.76 s, 10.81 s    largest/smallest = 2.58 testing is_coherent_all_xrange...    small/large/larger/verylarge duration: 6.52 s, 17.06 s, 17.44 s, 17.30 s    largest/smallest = 2.65 testing is_coherent_range...    small/large/larger/verylarge duration: 0.96 s, 4.14 s, 4.48 s, 4.48 s    largest/smallest = 4.66 

testing code:

import itertools import numpy np import timeit   setup = """ import numpy np def is_coherent_groupby(seq):     return len(list(g _, g in itertools.groupby(enumerate(seq), lambda (i,e): i-e))) == 1  def is_coherent_npdiff(x):     return all(np.diff(x) == 1)  def is_coherent_zip(seq):     return all(x==y+1 x, y in zip(seq[1:], seq))  def is_coherent_izip_longest(l):     return all(a==b a, b in itertools.izip_longest(l, xrange(l[0], l[-1]+1)))  def is_coherent_all_xrange(l):     return all(l[i] + 1 == l[i+1] in xrange(len(l)-1))  def is_coherent_range(seq):     return seq == range(seq[0], seq[-1]+1)   small_list = range(10**3) large_list = range(10**6) larger_list = range(10**7) very_large_list = range(10**8) """   fs = [     'is_coherent_groupby',     'is_coherent_npdiff',     'is_coherent_zip',     'is_coherent_izip_longest',     'is_coherent_all_xrange',     'is_coherent_range'     ]   n in fs:     print "testing %s..." % n     t1 = timeit.timeit(         '%s(small_list)' % n,          setup,         number=40000         )           t2 = timeit.timeit(         '%s(large_list)' % n,          setup,         number=100         )          t3 = timeit.timeit(         '%s(larger_list)' % n,          setup,         number=10         )     t4 =  timeit.timeit(         '%s(very_large_list)' % n,          setup,         number=1         )     print "   small/large/larger/verylarge duration: %.2f s, %.2f s, %.2f s, %.2f s" % (t1, t2, t3, t4)     print "   largest/smallest = %.2f" % (t4/t1) 

test machine:

  • linux 3.2.0 (ubuntu 12.04)
  • python 2.7.3 (gcc 4.1.2)
  • numpy 1.6.2 built intel compiler
  • cpu: e5-2650 @ 2.00ghz
  • 24 gb of memory

how bout

sorted_list = sorted(my_list) return sorted_list == range(sorted_list[0],sorted_list[-1]+1) 

or if coherent if sorted

return my_list == range(my_list[0],my_list[-1]+1) 

if using python 3 need list(range(...))


Comments

Popular posts from this blog

matlab - Deleting rows with specific rules -

jquery - How would i go about shortening this code? And to cancel the previous click on click of new section? -