Bisect, is it possible to work with descending sorted lists?

前端 未结 10 706
旧巷少年郎
旧巷少年郎 2020-12-09 15:37

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)  # -->         


        
相关标签:
10条回答
  • 2020-12-09 16:22

    You can insert like this

    bisect.insort_left(lists, -x)

    and extract elements like this

    value = - lists[i]
    
    0 讨论(0)
  • 2020-12-09 16:24

    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)
    
    0 讨论(0)
  • 2020-12-09 16:28

    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
    
    0 讨论(0)
  • 2020-12-09 16:33

    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...

    0 讨论(0)
提交回复
热议问题