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

alan.haffner at gmail.com alan.haffner at gmail.com
Thu Oct 11 01:10:11 EDT 2007


On Sep 28, 5:12 pm, Hrvoje Niksic <hnik... at xemacs.org> wrote:
> xkenneth <xkenn... 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.

Hrvoje,

   That's fun! thx.

 --Alan

the cut-n-paste version /w minor fix to 'lower'.
# ----------------------------------------------
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


def mycmp(s1, s2):
    return cmp(s1.lower(), s2.lower())


print ['foo', 'bar', 'baz'].index(Cmp('bar', mycmp))
print ['foo', 'bar', 'baz'].index(Cmp('Bar', mycmp))
try:
    print ['foo', 'bar', 'baz'].index(Cmp('nosuchelement', mycmp))
except ValueError:
    print "Search String not found!"

# end example




More information about the Python-list mailing list