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
Post a Comment