# Algorithm help per favore

Erik Max Francis max-resume at alcyone.com
Thu Jun 19 05:05:10 CEST 2003

Matt Shomphe wrote:

> built-in in 2.3).  Not sure about speed, but it *is* a one liner:
> >>> l = [6,3,3,3,5,7,6,3,4,4,3]
> >>> [x for i,x in enumerate(l) if l[i-1] != x or i == 0]
> [6, 3, 5, 7, 6, 3, 4, 3]

This contains a particularly subtle bug lurking for user-defined
sequence types which don't support the negative indices protocol.  A
much more solid solution, in my opinion, would be to test the index
_first_ and then test the subscripted value second:

>>> l = [6, 3, 3, 3, 5, 7, 6, 3, 4, 4, 3]
>>> [x for i, x in enumerate(l) if i == 0 or l[i - 1] != x]
[6, 3, 5, 7, 6, 3, 4, 3]

>>> class Range:
...  def __init__(self, n):
...   self.n = n
...  def __getitem__(self, i):
...   if 0 <= i < self.n: return i
...   else: raise IndexError
...
>>> l = Range(10) # raises IndexErrors on negative indices
>>> list(l) # see, it has a valid sequence interface
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [x for i, x in enumerate(l) if l[i - 1] != x or i == 0] # oops!
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 6, in __getitem__
IndexError

In general practices, it's a good idea to test the more stringent
condition first, before the second one, when you have short circuiting
logical operators like you do in Python (and most other modern
languages).

--
Erik Max Francis && max at alcyone.com && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/  \ Do we really want to go to Mars / Do we really want to try
\__/  Cassandra Wilson