2

I have list which is already sorted.

I often need to check to see

if foo in sortedlist:
    pass  # not really.  but not the point.

Is there a way to teach 'in' that sortedlist is sorted and that it should binary search the list?

4
  • 1
    possible duplicate of Binary Search in Python Commented May 10, 2014 at 6:29
  • Good question - It would be good to know how the search is conducted in sorted(my_list) too. Commented May 10, 2014 at 6:30
  • 1
    It's not possible to change the behavior of 'in'. What you're looking for is the the link pointed by Matt Ball (possible duplicate). Commented May 10, 2014 at 6:35
  • @ threadp: not quite true. See below. Commented May 10, 2014 at 6:56

2 Answers 2

4

Python favours explicit over implicit. Your options are to explicitly use the bisect module if you know your data is sorted, or create a subclass of list that implements __contains__ by using that module.

For example:

import bisect


class SortedList(list):
    def __contains__(self, elem):
        idx = bisect.bisect_left(self, elem)
        return idx < len(self) and self[idx] == elem

could be used as a substitute for list, and in will use __contains__ automatically. You'd probably want to override __setitem__, .extend() and .append() to maintain the list in sorted order, too.

Sign up to request clarification or add additional context in comments.

3 Comments

@MartijnPieters: your code is not correct: It raise a IndexError: list index out of range if elem is larger than the largest element of the list: the returned idx is len(self).
@MartijnPieters not on my machine... You should definitely check on yours.
@hivert: ah, no, I was indeed forgetting the elem > self[-1] case. Thanks for pointing that out. Corrected.
2

My suggestion would be to subclass list to use sorted list:

from bisect import bisect_left
class SortedList(list):
    def __init__(self, l):
        list.__init__(self, sorted(l))
    def __contains__(self, obj):
        pos = bisect_left(self, obj, 0, len(self))
        return (pos != len(self) and self[pos] == obj)

Then:

>>> l = SortedList([4,3,5435,123,54,2,343,23])
>>> l
[2, 3, 4, 23, 54, 123, 343, 5435]
>>> 23 in l
True
>>> 25 in l
False
>>> 123122 in l
False
>>> -1 in l
False

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.