i'm just wondering how I could check to verify that a list of numbers is arithmetic or not using python, so whether there is a common number in between each item in the list.
6 Answers
This is what I'd write:
all((i - j) == (j - k) for i, j, k in zip(l[:-2], l[1:-1], l[2:]))
You could probably make it more efficient by only computing the differences once, but if you're concerned about efficiency you'd use numpy and write:
np.all((a[:-2] - a[1:-1]) == (a[1:-1] - a[2:]))
or even (saving a slice):
np.all(a[:-2] + a[2:] == 2 * a[1:-1])
Probably the most concise method is to use numpy.diff, as it will automatically convert a list into a numpy array:
np.all(np.diff(l, 2) == 0)

- 152,476
- 27
- 293
- 366
You can use numpy.diff
if you have access to numpy
:
>>> a = numpy.array(range(1, 15, 2))
>>> numpy.diff(a)
array([2, 2, 2, 2, 2, 2])
So you can do
>>> d = numpy.diff(a)
>>> not numpy.any(d-d[0])
True
or even better
>>> not numpy.any(numpy.diff(a, 2))
True

- 63,701
- 20
- 147
- 175
-
Like the higher order diff, I'd forgotten about that! – ecatmur Nov 07 '12 at 19:08
-
hey unfortunately I don't have access to numpy :( great answer though :) – Belgin Fish Nov 07 '12 at 19:09
If you mean an arithmetic sequence as in a series of numbers such that each number is simply the equal to the previous one plus some constant amount (like [1, 3, 5, 7]
or [8, 18, 28, 38]
but not [1, 2, 4, 8]
or [1, 3, 1, 5, 1, 7]
) then you probably shouldn't overthink it. It is unlikely that a list comprehension outperforms this:
def is_arithmetic(l):
delta = l[1] - l[0]
for index in range(len(l) - 1):
if not (l[index + 1] - l[index] == delta):
return False
return True

- 4,365
- 3
- 24
- 22
-
A list comprehension would be worse, because it generates a list which is then thrown away (like your invocation of `range`). However, none of these answers are list comprehensions - they're generator comprehensions. – Eric Nov 07 '12 at 19:14
Here's a solution that only calculates the difference once:
from itertools import izip
def is_arithmetic(seq):
gen = (i - j for i, j in izip(seq[:-1], seq[1:]))
diff = next(gen, None) # get the first element in the generator
return all(d == diff for d in gen) # check all the others are equal to it
Or more cryptically:
def is_arithmetic(seq):
gen = (i - j for i, j in izip(seq[:-1], seq[1:]))
return all(d == d0 for d in gen for d0 in gen) # wat

- 95,302
- 53
- 242
- 374
What about examining the length of the set of all differences in the list?
>>> alist = [3,9,15,21,27,33,39,45,51,57]
>>> blist = [-7, -2, 3, 8, 13, 18, 23, 29]
>>> 1 == len(set([alist[x + 1] - alist[x] for x in range(len(alist) - 1)]))
True
>>> 1 == len(set([blist[x + 1] - blist[x] for x in range(len(blist) - 1)]))
False
>>>

- 1,372
- 9
- 12