How can I use bisect module on lists that are sorted descending? e.g.
import bisect
x = [1.0,2.0,3.0,4.0] # normal, ascending
bisect.insort(x,2.5) # -->
You can insert like this
bisect.insort_left(lists, -x)
and extract elements like this
value = - lists[i]
It is better to stick to the built-in python library, per @reve_etrange's comment unless you are working on a platform that allows you to use alternative C-extension implementations which might be faster. The following would leverage the built-in Python bisect module.
ASC = 'asc'
DESC = 'desc'
def bisect_left(l, e, lo=None, hi=None, order=ASC):
"""Find first index, starting from left, to insert e."""
lo = lo or 0
hi = hi or len(l)
if order not in (ASC, DESC):
raise ValueError('order must either be asc or desc.')
if order == ASC:
return bisect.bisect_left(l, e, lo, hi)
return len(l) - bisect.bisect_right(l[::-1], e, lo, hi)
def bisect_right(l, e, lo=None, hi=None, order=ASC):
"""Find first index, starting from right, to insert e."""
lo = lo or 0
hi = hi or len(l)
if order not in (ASC, DESC):
raise ValueError('order must either be asc or desc.')
if order == ASC:
return bisect.bisect_right(l, e, lo, hi)
return len(l) - bisect.bisect_left(l[::-1], e, lo, hi)
Slightly updated bisect
library code:
def reverse_bisect_right(a, x, lo=0, hi=None):
"""Return the index where to insert item x in list a, assuming a is sorted in descending order.
The return value i is such that all e in a[:i] have e >= x, and all e in
a[i:] have e < x. So if x already appears in the list, a.insert(x) will
insert just after the rightmost x already there.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
Essentially, the function returns number of elements in a which are >= than x.
>>> a = [8, 6, 5, 4, 2]
>>> reverse_bisect_right(a, 5)
3
>>> a[:reverse_bisect_right(a, 5)]
[8, 6, 5]
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if x > a[mid]: hi = mid
else: lo = mid+1
return lo
I had the same problem and since when I used ordered list.
I ended up with solution where I kept original list always in ascending order and just used reversed iterator when I needed to have descending order values.
This might not work with your problem...