Can I overload the compare (cmp()) function for a Lists ([]) index function?

Hrvoje Niksic hniksic at xemacs.org
Sat Sep 29 02:12:24 CEST 2007


xkenneth <xkenneth at gmail.com> writes:

> Looking to do something similair. I'm working with alot of timestamps
> and if they're within a couple seconds I need them to be indexed and
> removed from a list.
> Is there any possible way to index with a custom cmp() function?
>
> I assume it would be something like...
>
> list.index(something,mycmp)

The obvious option is reimplementing the functionality of index as an
explicit loop, such as:

def myindex(lst, something, mycmp):
    for i, el in enumerate(lst):
        if mycmp(el, something) == 0:
            return i
    raise ValueError("element not in list")

Looping in Python is slower than looping in C, but since you're
calling a Python function per element anyway, the loop overhead might
be negligible.

A more imaginative way is to take advantage of the fact that index
uses the '==' operator to look for the item.  You can create an object
whose == operator calls your comparison function and use that object
as the argument to list.index:

class Cmp(object):
    def __init__(self, item, cmpfun):
        self.item = item
        self.cmpfun = cmpfun
    def __eq__(self, other):
        return self.cmpfun(self.item, other) == 0

# list.index(Cmp(something, mycmp))

For example:

>>> def mycmp(s1, s2):
...   return cmp(s1.tolower(), s2.tolower())
>>> ['foo', 'bar', 'baz'].index(Cmp('bar', mycmp))
1
>>> ['foo', 'bar', 'baz'].index(Cmp('Bar', mycmp))
1
>>> ['foo', 'bar', 'baz'].index(Cmp('nosuchelement', mycmp))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.index(x): x not in list

The timeit module shows, somewhat surprisingly, that the first method
is ~1.5 times faster, even for larger lists.



More information about the Python-list mailing list