Example #1
0
class RangeList:
    """Add and query non-overlapping intervals. Intervals are semi-closed, e.g.
    the interval [1, 3) contains the points {1, 2}.
    """
    def __init__(self, init=None):
        self.data = SortedList(init, key=lambda x: x[0])

    def add(self, start, end):
        left = self.data.bisect_right((start, 0))
        if left > 0:
            if self.data[left - 1][1] >= start:
                start = self.data[left - 1][0]
                left -= 1

        right = self.data.bisect_right((end, 0))
        if right > 0:
            if self.data[right - 1][1] >= end:
                end = self.data[right - 1][1]

        for _ in range(right - left):
            self.data.pop(left)

        self.data.add((start, end))

    def list(self):
        return list(self.data)

    def iter(self):
        return self.data.islice(start=0)
Example #2
0
class OrderBook:

    def __init__(self, bids=[], asks=[]):
        self.bids = SortedList(bids, key = lambda order: -order.price)
        self.asks = SortedList(asks, key = lambda order: order.price)

    def __len__(self):
        return len(self.bids) + len(self.asks)

    def best_bid(self):
        if len(self.bids) > 0:
            return self.bids[0].price
        else:
            return 0

    def best_ask(self):
        if len(self.asks) > 0:
            return self.asks[0].price
        else:
            return 0

    def add(self, order):
        if order.side == 'buy':
            index = self.bids.bisect_right(order)
            self.bids.insert(index, order)
        elif order.side == 'sell':
            index = self.asks.bisect_right(order)
            self.asks.insert(index, order)

    def remove(self, order):
        if order.side == 'buy':
            self.bids.remove(order)
        elif order.side == 'sell':
            self.asks.remove(order)
Example #3
0
class RangeModule:
    def __init__(self):
        self.nums = SortedList()

    def addRange(self, left: int, right: int) -> None:
        l = self.nums.bisect_left(left)
        r = self.nums.bisect_right(right)

        for _ in range(r - l):
            self.nums.pop(l)
        if l % 2 == 0:
            self.nums.add(left)
        if r % 2 == 0:
            self.nums.add(right)

    def queryRange(self, left: int, right: int) -> bool:
        l = self.nums.bisect_right(left)
        r = self.nums.bisect_left(right)
        return l == r and l % 2 != 0

    def removeRange(self, left: int, right: int) -> None:
        l = self.nums.bisect_left(left)
        r = self.nums.bisect_right(right)
        for _ in range(r - l):
            self.nums.pop(l)
        if l % 2 != 0:
            self.nums.add(left)
        if r % 2 != 0:
            self.nums.add(right)
class MKAverage:
    LESS_THAN_M_ELEMENT = -1

    def __init__(self, m: int, k: int):
        """
        :param m: 3 <= m <= 1e5
        :param k: 1 <= 2 * k <= m
        """
        self.k = k
        self.m = m
        # stream of last m elements
        self.stream = deque()
        # sorted list of the last m elements
        self.sorted_m = SortedList()
        # sum of k smallest elements
        self.sum_bottom_k = 0
        # sum of m - k smallest elements
        self.sum_bottom_m_minus_k = 0

    def add_element(self, num: int) -> None:
        """
        :param num: 1 <= num <= 1e5
        """
        self.stream.append(num)

        if len(self.stream) > self.m:
            drop_off_num = self.stream.popleft()
            r = self.sorted_m.bisect_right(drop_off_num)
            # Update self.sum_bottom_k
            if r <= self.k:
                self.sum_bottom_k -= drop_off_num
                self.sum_bottom_k += self.sorted_m[self.k]
            # Update self.sum_bottom_m_minus_k
            if r <= self.m - self.k:
                self.sum_bottom_m_minus_k -= drop_off_num
                self.sum_bottom_m_minus_k += self.sorted_m[self.m - self.k]
            self.sorted_m.remove(drop_off_num)

        r = self.sorted_m.bisect_right(num)
        # Update self.sum_bottom_k
        if r < self.k:
            if len(self.sorted_m) >= self.k:
                self.sum_bottom_k -= self.sorted_m[self.k - 1]
            self.sum_bottom_k += num
        # Update self.sum_bottom_m_minus_k
        if r < self.m - self.k:
            if len(self.sorted_m) >= self.m - self.k:
                self.sum_bottom_m_minus_k -= self.sorted_m[self.m - self.k - 1]
            self.sum_bottom_m_minus_k += num
        self.sorted_m.add(num)

    def calculate_mk_average(self) -> int:
        """
        :return: return average of the middle (m - 2 * k) values if stream have reached m elements,
            else LESS_THAN_M_ELEMENT
        """
        if len(self.sorted_m) < self.m:
            return MKAverage.LESS_THAN_M_ELEMENT
        return (self.sum_bottom_m_minus_k - self.sum_bottom_k) // (self.m - self.k * 2)
Example #5
0
def test_bisect_right():
    slt = SortedList()
    assert slt.bisect_right(10) == 0
    slt = SortedList(range(100), load=17)
    slt.update(range(100))
    slt._check()
    assert slt.bisect_right(10) == 22
    assert slt.bisect_right(200) == 200
def test_bisect_right():
    slt = SortedList()
    assert slt.bisect_right(10) == 0
    slt = SortedList(range(100), load=17)
    slt.update(range(100))
    slt._check()
    assert slt.bisect_right(10) == 22
    assert slt.bisect_right(200) == 200
class OrderBook:

    # Constructor con dos arreglos de entrada bid/ask para las ordenes tipo limite.
    def __init__(self, bids=[], asks=[]):
        # Ordena la lista de compra de mayor a menor y la asigna al arreglo bids.
        self.bids = SortedList(bids, key = lambda order: -order.price)
        # Ordena la lista de venta de menor a mayor y la asigna al arreglo asks.
        self.asks = SortedList(asks, key = lambda order: order.price)

    # Obtiene tamaño de los arreglos
    def __len__(self):
        return len(self.bids) + len(self.asks)

    # Obtiene la mayor oferta de compra que es la posicion 0 del arreglo
    def best_bid(self):
        if len(self.bids) > 0:
            return self.bids[0].price
        else:
            return 0

    # Obtiene la menor oferta de venta que es la posicion 0 del arreglo
    def best_ask(self):
        if len(self.asks) > 0:
            return self.asks[0].price
        else:
            return 0

    # Funcion para agregar una nueva orden al libro de ordenes.
    def add(self, order):
        # Adiciona la nueva orden al arreglo de bids
        if order.side == 'buy':
            index = self.bids.bisect_right(order)
            self.bids.add(order)
        # Adiciona la nueva orden al arreglo de asks
        elif order.side == 'sell':
            index = self.asks.bisect_right(order)
            self.asks.add(order)

    # Funcion para eliminar una orden al libro de ordenes.
    def remove(self, order):
        # Elimina la orden al arreglo de bids
        if order.side == 'buy':
            self.bids.remove(order)
        # Elimina la orden al arreglo de asks
        elif order.side == 'sell':
            self.asks.remove(order)

    def getSizeOfBids(self):
        return len(self.bids)

    def getSizeOfAsks(self):
        return len(self.asks)
Example #8
0
 def find132pattern(self, nums):
     """
     :type nums: List[int]
     :rtype: bool
     """
     # i, j, k
     # ai < ak < aj
     left_min = nums[0]
     # o(nlogn)
     right_list = SortedList(nums[1:])
     
     # o(n)
     for j in range(1, len(nums) - 1):
         right_list.remove(nums[j])
         
         if left_min < nums[j]: 
             # o(logn)
             index = right_list.bisect_right(left_min)
             # print "Testing [%s, nums[%s]=%s, nums[%s]=%s]" % (left_min, j, nums[j], index, right_list[index])
             if index < len(right_list) and right_list[index] < nums[j] and left_min < right_list[index]:
                 return True
         else:
             left_min = nums[j]    
             
     return False
Example #9
0
class Comparision(object):
    def __init__(self, size):
        self._histograms = collections.deque(maxlen=size)
        self._sorted_hist = SortedList()

    def add(self, value):
        if len(self._histograms) == self._histograms.maxlen:
            self._sorted_hist.remove(self._histograms[0])

        self._histograms.append(value)
        self._sorted_hist.add(value)

    def _get_lt_count(self, value):
        return self._sorted_hist.bisect_left(value=value)

    def _get_le_count(self, value):
        return self._sorted_hist.bisect_right(value=value)

    def _get_size(self):
        return len(self._histograms)

    def get_rate(self, value):
        return self._get_lt_count(value) / self._get_size()

    def is_topk(self, value, k):
        if self._get_size() <= k:
            return True

        return self._get_size() - self._get_le_count(value) < k
Example #10
0
class RangeModule:
    def __init__(self):
        self.treelist = SortedList(key=lambda r: r[0])

    def addRange(self, left: int, right: int) -> None:
        lefti = self.treelist.bisect_left([left, left])
        leftRange, rightRange = None, None
        added = False
        if lefti > 0:
            leftRange = self.treelist[lefti - 1]
            if leftRange[1] >= left:  # 左边区间与当前区间有重叠,2个区间进行合并
                leftRange[1] = max(right, leftRange[1])
                added = True
        righti = self.treelist.bisect_right([right, right])
        if righti - 1 > 0:
            rightRange = self.treelist[righti - 1]
            if rightRange[0] <= right <= rightRange[1]:
                rightRange[0] = min(rightRange[0], left)
                rightRange[1] = max(rightRange[1], right)
                added = True
        for i in range(lefti, righti - 1):  # 删除左右边界内的区间
            del self.treelist[lefti]
        if not added:
            self.treelist.add([left, right])

    def queryRange(self, left: int, right: int) -> bool:
        index = self.treelist.bisect_left([left, right])
        if index < len(self.treelist):
            leftRange = self.treelist[index]
            if leftRange[0] <= left and leftRange[1] >= right:
                return True
        return False

    def removeRange(self, left: int, right: int) -> None:
        pass
 def createSortedArray(self, instructions):
     l = SortedList()
     res = 0
     for i in instructions:
         res += min(l.bisect_left(i), len(l) - l.bisect_right(i))
         l.add(i)
     return res % (10**9 + 7)
Example #12
0
    def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
        if not nums: return False
        if t == 0 and len(nums) == len(set(nums)):
            # Quick response for special case on t = 0
            # t = 0 requires at last one pair of duplicate elements
            return False
        n = len(nums)
        i, j = -k, min(n - 1, k)
        sorted = SortedList()
        # init
        for p in range(i, j + 1):
            if p < 0: continue
            sorted.add(nums[p])

        for step in range(n):
            gap = 0xffffffff
            l, r, idx = sorted.bisect_left(nums[step]), sorted.bisect_right(nums[step]), sorted.index(nums[step])
            if r - l >= 2 and t >= 0: return True
            if l - 1 >= 0:
                gap = min(nums[step] - sorted[l - 1], gap)
            if r < len(sorted):
                gap = min(gap, sorted[r] - nums[step])
            if gap <= t: return True
            # move on
            if i >= 0:
                sorted.remove(nums[i])
            if j + 1 < n: sorted.add(nums[j + 1])
            i += 1
            j += 1
Example #13
0
def minInteger(num, k):
    """
    :type num: str
    :type k: int
    :rtype: str
    """
    index_dict = defaultdict(deque)
    used = SortedList()
    ret = []
    N = len(num)

    for i, num in enumerate(num):
        index_dict[num].append(i)

    for i in range(N):
        for digit in digits:
            if not index_dict[digit]: continue
            idx = index_dict[digit][0]
            num_swaps = idx - used.bisect_right(idx)

            if num_swaps <= k:
                k -= num_swaps
                ret.append(digit)
                used.add(idx)
                index_dict[digit].popleft()
                break

    return "".join(ret)
Example #14
0
def _test5():
    """
    网址:http://www.grantjenks.com/docs/sortedcontainers/sortedlist.html
    """
    from sortedcontainers import SortedList
    # 定义
    sl = SortedList(key=lambda x: -x)  # 降序
    sl = SortedList([3, 1, 2, 1, 5, 4])  # 升序
    print(sl)  # SortedList([1, 1, 2, 3, 4, 5])
    # 插入、删除元素
    sl.add(3)
    sl.add(3)
    sl.discard(2)  # SortedList([1, 1, 3, 3, 3, 4, 5])
    print(sl)
    # 统计某个元素出现的次数
    print(sl.count(3))  # 3
    # 返回第一个和最后一个元素
    print(sl[0])  # 1
    print(sl[-1])  # 5
    # 遍历 set
    for e in sl:
        print(e, end=", ")  # 1, 1, 3, 3, 3, 4, 5,
    print()
    # 判断某元素是否存在
    print(2 in sl)  # False
    # bisect_left() / bisect_right()
    print(sl.bisect_left(3))  # 返回大于等于3的最小元素对应的下标    2
    print(sl.bisect_right(3))  # 返回大于3的最小元素对应的下标    5
    # 清空
    sl.clear()
    print(len(sl))  # 0
    print(len(sl) == 0)  # True
Example #15
0
 def createSortedArray(self, instructions: List[int]) -> int:
     nums = SortedList()
     cost = 0
     for num in instructions:
         cost += min(nums.bisect_left(num), len(nums)-nums.bisect_right(num))
         nums.add(num)
     return cost % Solution.MOD
Example #16
0
    def fallingSquares(self, positions: List[List[int]]) -> List[int]:
        treeList = SortedList(key=lambda r: r[0])
        ans = []
        maxHeight = 0
        for p in positions:
            bottomHeight = 0  # 与当前区间有交集的区间中最高高度
            left, right, height = p[0], p[0] + p[1] - 1, p[1]
            lefti = treeList.bisect_left([left, left])
            if lefti > 0:
                leftRange = treeList[lefti - 1]
                if leftRange[1] >= left and leftRange[1] <= right:  # 左边的区间与当前区间有交集,且其右边界没有超过当前区间的右边界
                    leftRange[1] = left - 1  # 裁剪左边区间的右边界
                    bottomHeight = leftRange[2]
                elif leftRange[1] > right:  # 左边的区间右边界已经超过了当前区间右边界,需要将左边的区间拆分成2部分,一部分在当前区间左边,另外一部分在右边
                    rightRange = [right + 1, leftRange[1], leftRange[2]]  # 在右边新添加一个区间
                    treeList.add(rightRange)
                    leftRange[1] = left - 1  # 裁剪原左边区间的右边界
                    bottomHeight = leftRange[2]
            righti = treeList.bisect_right([right, right])
            if righti - 1 > 0:
                rightRange = treeList[righti - 1]
                if rightRange[0] <= right <= rightRange[1] and rightRange[0] != rightRange[1]:  # 右边的区间与当前区间有交集,且右边区间没有完全被当前区间覆盖
                    rightRange[0] = right - 1  # 裁剪右边区间的左边界
                    bottomHeight = max(bottomHeight, rightRange[2])
                elif rightRange[0] <= right <= rightRange[1] and rightRange[0] == rightRange[1]:  # 右边的区间被当前区间完全覆盖,删除
                    del treeList[righti - 1]
                    bottomHeight = max(bottomHeight, rightRange[2])
            for i in range(lefti, righti - 1):  # 删除左右边界内的区间
                bottomHeight = max(bottomHeight, treeList[lefti][2])
                del treeList[lefti]
            treeList.add([left, right, height + bottomHeight])  # 当前方块加入集合
            maxHeight = max(maxHeight, height + bottomHeight)
            ans.append(maxHeight)

        return ans
Example #17
0
    def goodTriplets(self, nums1: List[int], nums2: List[int]) -> int:
        n = len(nums1)
        pos2 = [-1] * n
        for i in range(n):
            x = nums2[i]
            pos2[x] = i

        pos1 = [-1] * n
        for i in range(n):
            x = nums1[i]
            p = pos2[x]
            pos1[i] = p

        left = SortedList()
        right = SortedList(pos1)
        ans = 0
        for i in range(n):
            p = pos1[i]
            right.remove(p)
            left.add(p)
            # search how many elements in left is < p
            # and how many elements in right is > p
            a = left.bisect_left(p)
            b = len(right) - right.bisect_right(p)
            ans += a * b
        return ans
Example #18
0
class CountIntervals(object):
    def __init__(self):
        self.__sl = SortedList()
        self.__cnt = 0

    def add(self, left, right):
        """
        :type left: int
        :type right: int
        :rtype: None
        """
        i = self.__sl.bisect_right((left, ))
        if i - 1 >= 0 and self.__sl[i - 1][1] + 1 >= left:
            i -= 1
            left = self.__sl[i][0]
        to_remove = []
        for i in xrange(i, len(self.__sl)):
            if not (right + 1 >= self.__sl[i][0]):
                break
            right = max(right, self.__sl[i][1])
            self.__cnt -= self.__sl[i][1] - self.__sl[i][0] + 1
            to_remove.append(i)
        while to_remove:
            del self.__sl[to_remove.pop()]
        self.__sl.add((left, right))
        self.__cnt += right - left + 1

    def count(self):
        """
        :rtype: int
        """
        return self.__cnt
Example #19
0
    class LevelMetadata():
        def __init__(self):
            self.uuids = list()
            self.first_indices = SortedList()

        def __len__(self):
            return len(self.uuids)

        def insert(self, uuid, first_index):
            idx = self.first_indices.bisect_left(first_index)
            self.first_indices.add(first_index)
            self.uuids.insert(idx, uuid)

        def clear(self, i=None, j=None):
            if i is None and j is None:
                self.uuids.clear()
                self.first_indices.clear()
            else:
                del self.uuids[i:j]
                del self.first_indices[i:j]

        def get_uuid(self, item):
            idx = self.first_indices.bisect_right(item) - 1
            if idx < 0:
                return None
            return self.uuids[idx]
Example #20
0
 def createSortedArray(self, instructions: List[int]) -> int:
     sorted_list = SortedList()
     total_cost = 0
     for num in instructions:
         total_cost += min( sorted_list.bisect_left(num), len(sorted_list)-sorted_list.bisect_right(num) )
         sorted_list.add(num)
     return total_cost % Solution.MOD
 def createSortedArray(self, instructions: List[int]) -> int:
     sorted_list = SortedList()
     ans = 0
     for i in instructions:
         ans += min(sorted_list.bisect_left(i),
                    len(sorted_list) - sorted_list.bisect_right(i))
         sorted_list.add(i)
     return ans % (100**9 + 7)
 def createSortedArray(self, instructions: List[int]) -> int:
     sorted_list, cost = SortedList(), 0
     for i in range(len(instructions)):
         left_cost = sorted_list.bisect_left(instructions[i])
         right_cost = i - sorted_list.bisect_right(instructions[i])
         cost += min(left_cost, right_cost)
         sorted_list.add(instructions[i])
     return cost % (10**9 + 7)
Example #23
0
class Events:
    '''
    This class holds a series of ALT signals in an optimized datastructure for
    efficient queries.
    '''
    def __init__(self, event=None):
        self.events = SortedList(key=lambda x: x.time)
        self.current = 0
        if (event is not None):
            self.events.add(event)

    def __str__(self):
        return f'Events:(total={len(self)})'

    def __len__(self):
        return len(self.events)

    def add(self, e):
        self.events.add(e)

    def run(self):
        for e in self.events:
            yield e

    def next(self, t):
        ind = self.events.bisect_right(t)
        if ind < 0 or ind >= len(self):
            return []
        k = ind
        for i in range(ind + 1, len(self)):
            if (self.events[ind].time == self.events[i].time):
                k = i
            else:
                break
        if k < 0 or k >= len(self):
            return []
        ind = k
        out = [self.events[ind]]
        for i in range(ind + 1, len(self)):
            if self.events[i].time == self.events[ind].time:
                out.append(a[i])
            else:
                break
        return out

    def union(self, E):
        self.events = self.events + E.events

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= len(self):
            self.current = 0
            raise StopIteration
        else:
            self.current += 1
            return self.events[self.current - 1]
Example #24
0
def find_diamond(storge, min_weight):
    storge = SortedList(storge)
    position = storge.bisect_right(min_weight)
    if position == len(storge):
        return None
    elif storge[position - 1] != min_weight:
        return storge[position]
    else:
        return storge[position - 1]
Example #25
0
    def createSortedArray(self, instructions):
        SList = SortedList()
        ans = 0
        for num in instructions:
            ans += min(SList.bisect_left(num),
                       len(SList) - SList.bisect_right(num))
            SList.add(num)

        return ans % 1000000007
Example #26
0
 def createSortedArray(self, instructions: List[int]) -> int:
     nums = SortedList()
     cost = 0
     l = 0
     for n in instructions:
         cost += min(nums.bisect_left(n), l - nums.bisect_right(n))
         nums.add(n)
         l += 1
     return cost % ((10**9) + 7)
Example #27
0
    def advantageCount(self, A: List[int], B: List[int]) -> List[int]:
        sl = SortedList(A)

        for i, b in enumerate(B):
            index = 0 if sl[-1] <= b else sl.bisect_right(b)
            A[i] = sl[index]
            del sl[index]

        return A
 def createSortedArray2(self, instructions) -> int:
     nums = SortedList()
     res = 0
     for n in instructions:
         smaller = nums.bisect_left(n)
         larger = len(nums) - nums.bisect_right(n)
         nums.add(n)
         res += min(smaller, larger)
     return res % (10**9 + 7)
Example #29
0
 def createSortedArray(self, instructions: List[int]) -> int:
     sortL = SortedList()
     retVal = 0
     for val in instructions:
         retVal += min(sortL.bisect_left(val),
                       len(sortL) - sortL.bisect_right(val))
         retVal %= (10**9 + 7)
         sortL.add(val)
     return retVal
 def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:
     from sortedcontainers import SortedList
     prefix, ret = 0, 0
     st = SortedList([0])
     for num in nums:
         prefix += num
         ret += st.bisect_right(prefix - lower) - st.bisect_left(prefix - upper)
         st.add(prefix)
     return ret
Example #31
0
    def createSortedArray(self, instructions: List[int]) -> int:
        SList = SortedList()
        ans = 0
        for num in instructions:
            ans += min(SList.bisect_left(num), len(SList) - SList.bisect_right(num))
            ans %= (10 ** 9 + 7)
            SList.add(num)

        return ans
Example #32
0
class PriorityDict(MutableMapping):
    """
    A PriorityDict provides the same methods as a dict. Additionally, a
    PriorityDict efficiently maintains its keys in value sorted order.
    Consequently, the keys method will return the keys in value sorted order,
    the popitem method will remove the item with the highest value, etc.
    """
    def __init__(self, *args, **kwargs):
        """
        A PriorityDict provides the same methods as a dict. Additionally, a
        PriorityDict efficiently maintains its keys in value sorted order.
        Consequently, the keys method will return the keys in value sorted
        order, the popitem method will remove the item with the highest value,
        etc.
        If the first argument is the boolean value False, then it indicates
        that keys are not comparable. By default this setting is True and
        duplicate values are tie-breaked on the key. Using comparable keys
        improves the performance of the PriorityDict.
        An optional *iterable* argument provides an initial series of items to
        populate the PriorityDict.  Each item in the sequence must itself
        contain two items. The first is used as a key in the new dictionary,
        and the second as the key's value. If a given key is seen more than
        once, the last value associated with it is retained in the new
        dictionary.
        If keyword arguments are given, the keywords themselves with their
        associated values are added as items to the dictionary. If a key is
        specified both in the positional argument and as a keyword argument, the
        value associated with the keyword is retained in the dictionary. For
        example, these all return a dictionary equal to ``{"one": 2, "two":
        3}``:
        * ``SortedDict(one=2, two=3)``
        * ``SortedDict({'one': 2, 'two': 3})``
        * ``SortedDict(zip(('one', 'two'), (2, 3)))``
        * ``SortedDict([['two', 3], ['one', 2]])``
        The first example only works for keys that are valid Python
        identifiers; the others work with any valid keys.
        Note that this constructor mimics the Python dict constructor. If
        you're looking for a constructor like collections.Counter(...), see
        PriorityDict.count(...).
        """
        self._dict = dict()

        if len(args) > 0 and isinstance(args[0], bool):
            if args[0]:
                self._list = SortedList()
            else:
                self._list = SortedListWithKey(key=lambda tup: tup[0])
        else:
            self._list = SortedList()

        self.iloc = _IlocWrapper(self)
        self.update(*args, **kwargs)

    def clear(self):
        """Remove all elements from the dictionary."""
        self._dict.clear()
        self._list.clear()

    def clean(self, value=0):
        """
        Remove all items with value less than or equal to `value`.
        Default `value` is 0.
        """
        _list, _dict = self._list, self._dict
        pos = self.bisect_right(value)
        for key in (key for value, key in _list[:pos]):
            del _dict[key]
        del _list[:pos]

    def __contains__(self, key):
        """Return True if and only if *key* is in the dictionary."""
        return key in self._dict

    def __delitem__(self, key):
        """
        Remove ``d[key]`` from *d*.  Raises a KeyError if *key* is not in the
        dictionary.
        """
        value = self._dict[key]
        self._list.remove((value, key))
        del self._dict[key]

    def __getitem__(self, key):
        """
        Return the priority of *key* in *d*.  Raises a KeyError if *key* is not
        in the dictionary.
        """
        return self._dict[key]

    def __iter__(self):
        """
        Create an iterator over the keys of the dictionary ordered by the value
        sort order.
        """
        return iter(key for value, key in self._list)

    def __reversed__(self):
        """
        Create an iterator over the keys of the dictionary ordered by the
        reversed value sort order.
        """
        return iter(key for value, key in reversed(self._list))

    def __len__(self):
        """Return the number of (key, value) pairs in the dictionary."""
        return len(self._dict)

    def __setitem__(self, key, value):
        """Set `d[key]` to *value*."""
        if key in self._dict:
            old_value = self._dict[key]
            self._list.remove((old_value, key))
        self._list.add((value, key))
        self._dict[key] = value

    def copy(self):
        """Create a shallow copy of the dictionary."""
        result = PriorityDict()
        result._dict = self._dict.copy()
        result._list = self._list.copy()
        result.iloc = _IlocWrapper(result)
        return result

    def __copy__(self):
        """Create a shallow copy of the dictionary."""
        return self.copy()

    @classmethod
    def fromkeys(cls, iterable, value=0):
        """
        Create a new dictionary with keys from `iterable` and values set to
        `value`. The default *value* is 0.
        """
        return PriorityDict((key, value) for key in iterable)

    def get(self, key, default=None):
        """
        Return the value for *key* if *key* is in the dictionary, else
        *default*.  If *default* is not given, it defaults to ``None``,
        so that this method never raises a KeyError.
        """
        return self._dict.get(key, default)

    def has_key(self, key):
        """Return True if and only in *key* is in the dictionary."""
        return key in self._dict

    def pop(self, key, default=_NotGiven):
        """
        If *key* is in the dictionary, remove it and return its value,
        else return *default*. If *default* is not given and *key* is not in
        the dictionary, a KeyError is raised.
        """
        if key in self._dict:
            value = self._dict[key]
            self._list.remove((value, key))
            return self._dict.pop(key)
        else:
            if default == _NotGiven:
                raise KeyError
            else:
                return default

    def popitem(self, index=-1):
        """
        Remove and return item at *index* (default: -1). Raises IndexError if
        dict is empty or index is out of range. Negative indices are supported
        as for slice indices.
        """
        value, key = self._list.pop(index)
        del self._dict[key]
        return key, value

    def setdefault(self, key, default=0):
        """
        If *key* is in the dictionary, return its value.  If not, insert *key*
        with a value of *default* and return *default*.  *default* defaults to
        ``0``.
        """
        if key in self._dict:
            return self._dict[key]
        else:
            self._dict[key] = default
            self._list.add((default, key))
            return default

    def elements(self):
        """
        Return an iterator over elements repeating each as many times as its
        count. Elements are returned in value sort-order. If an element’s count
        is less than one, elements() will ignore it.
        """
        values = (repeat(key, value) for value, key in self._list)
        return chain.from_iterable(values)

    def most_common(self, count=None):
        """
        Return a list of the `count` highest priority elements with their
        priority. If `count` is not specified, `most_common` returns *all*
        elements in the dict. Elements with equal counts are ordered by key.
        """
        _list, _dict = self._list, self._dict

        if count is None:
            return [(key, value) for value, key in reversed(_list)]

        end = len(_dict)
        start = end - count

        return [(key, value) for value, key in reversed(_list[start:end])]

    def subtract(self, elements):
        """
        Elements are subtracted from an iterable or from another mapping (or
        counter). Like dict.update() but subtracts counts instead of replacing
        them. Both inputs and outputs may be zero or negative.
        """
        self -= Counter(elements)

    def tally(self, *args, **kwargs):
        """
        Elements are counted from an iterable or added-in from another mapping
        (or counter). Like dict.update() but adds counts instead of replacing
        them. Also, the iterable is expected to be a sequence of elements, not a
        sequence of (key, value) pairs.
        """
        self += Counter(*args, **kwargs)

    @classmethod
    def count(self, *args, **kwargs):
        """
        Consume `args` and `kwargs` with a Counter and use that mapping to
        initialize a PriorityDict.
        """
        return PriorityDict(Counter(*args, **kwargs))

    def update(self, *args, **kwargs):
        """
        Update the dictionary with the key/value pairs from *other*, overwriting
        existing keys.
        *update* accepts either another dictionary object or an iterable of
        key/value pairs (as a tuple or other iterable of length two).  If
        keyword arguments are specified, the dictionary is then updated with
        those key/value pairs: ``d.update(red=1, blue=2)``.
        """
        _list, _dict = self._list, self._dict

        if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], Mapping):
            items = args[0]
        else:
            items = dict(*args, **kwargs)

        if (10 * len(items)) > len(_dict):
            _dict.update(items)
            _list.clear()
            _list.update((value, key) for key, value in iteritems(_dict))
        else:
            for key, value in iteritems(items):
                old_value = _dict[key]
                _list.remove((old_value, key))
                _dict[key] = value
                _list.add((value, key))

    def index(self, key):
        """
        Return the smallest *i* such that `d.iloc[i] == key`.  Raises KeyError
        if *key* is not present.
        """
        value = self._dict[key]
        return self._list.index((value, key))

    def bisect_left(self, value):
        """
        Similar to the ``bisect`` module in the standard library, this returns
        an appropriate index to insert *value* in PriorityDict. If *value* is
        already present in PriorityDict, the insertion point will be before (to
        the left of) any existing entries.
        """
        return self._list.bisect_left((value,))

    def bisect(self, value):
        """Same as bisect_left."""
        return self._list.bisect((value,))

    def bisect_right(self, value):
        """
        Same as `bisect_left`, but if *value* is already present in
        PriorityDict, the insertion point will be after (to the right
        of) any existing entries.
        """
        return self._list.bisect_right((value, _Biggest))

    def __iadd__(self, that):
        """Add values from `that` mapping."""
        _list, _dict = self._list, self._dict
        if len(_dict) == 0:
            _dict.update(that)
            _list.update((value, key) for key, value in iteritems(_dict))
        elif len(that) * 3 > len(_dict):
            _list.clear()
            for key, value in iteritems(that):
                if key in _dict:
                    _dict[key] += value
                else:
                    _dict[key] = value
            _list.update((value, key) for key, value in iteritems(_dict))
        else:
            for key, value in iteritems(that):
                if key in _dict:
                    old_value = _dict[key]
                    _list.remove((old_value, key))
                    value = old_value + value
                _dict[key] = value
                _list.add((value, key))
        return self

    def __isub__(self, that):
        """Subtract values from `that` mapping."""
        _list, _dict = self._list, self._dict
        if len(_dict) == 0:
            _dict.clear()
            _list.clear()
        elif len(that) * 3 > len(_dict):
            _list.clear()
            for key, value in iteritems(that):
                if key in _dict:
                    _dict[key] -= value
            _list.update((value, key) for key, value in iteritems(_dict))
        else:
            for key, value in iteritems(that):
                if key in _dict:
                    old_value = _dict[key]
                    _list.remove((old_value, key))
                    value = old_value - value
                    _dict[key] = value
                    _list.add((value, key))
        return self

    def __ior__(self, that):
        """Or values from `that` mapping (max(v1, v2))."""
        _list, _dict = self._list, self._dict
        if len(_dict) == 0:
            _dict.update(that)
            _list.update((value, key) for key, value in iteritems(_dict))
        elif len(that) * 3 > len(_dict):
            _list.clear()
            for key, value in iteritems(that):
                if key in _dict:
                    old_value = _dict[key]
                    _dict[key] = old_value if old_value > value else value
                else:
                    _dict[key] = value
            _list.update((value, key) for key, value in iteritems(_dict))
        else:
            for key, value in iteritems(that):
                if key in _dict:
                    old_value = _dict[key]
                    _list.remove((old_value, key))
                    value = old_value if old_value > value else value
                _dict[key] = value
                _list.add((value, key))
        return self

    def __iand__(self, that):
        """And values from `that` mapping (min(v1, v2))."""
        _list, _dict = self._list, self._dict
        if len(_dict) == 0:
            _dict.clear()
            _list.clear()
        elif len(that) * 3 > len(_dict):
            _list.clear()
            for key, value in iteritems(that):
                if key in _dict:
                    old_value = _dict[key]
                    _dict[key] = old_value if old_value < value else value
            _list.update((value, key) for key, value in iteritems(_dict))
        else:
            for key, value in iteritems(that):
                if key in _dict:
                    old_value = _dict[key]
                    _list.remove((old_value, key))
                    value = old_value if old_value < value else value
                    _dict[key] = value
                    _list.add((value, key))
        return self

    def __add__(self, that):
        """Add values from this and `that` mapping."""
        result = PriorityDict()
        _list, _dict = result._list, result._dict
        _dict.update(self._dict)
        for key, value in iteritems(that):
            if key in _dict:
                _dict[key] += value
            else:
                _dict[key] = value
        _list.update((value, key) for key, value in iteritems(_dict))
        return result

    def __sub__(self, that):
        """Subtract values in `that` mapping from this."""
        result = PriorityDict()
        _list, _dict = result._list, result._dict
        _dict.update(self._dict)
        for key, value in iteritems(that):
            if key in _dict:
                _dict[key] -= value
        _list.update((value, key) for key, value in iteritems(_dict))
        return result

    def __or__(self, that):
        """Or values from this and `that` mapping."""
        result = PriorityDict()
        _list, _dict = result._list, result._dict
        _dict.update(self._dict)
        for key, value in iteritems(that):
            if key in _dict:
                old_value = _dict[key]
                _dict[key] = old_value if old_value > value else value
            else:
                _dict[key] = value
        _list.update((value, key) for key, value in iteritems(_dict))
        return result

    def __and__(self, that):
        """And values from this and `that` mapping."""
        result = PriorityDict()
        _list, _dict = result._list, result._dict
        _dict.update(self._dict)
        for key, value in iteritems(that):
            if key in _dict:
                old_value = _dict[key]
                _dict[key] = old_value if old_value < value else value
        _list.update((value, key) for key, value in iteritems(_dict))
        return result

    def __eq__(self, that):
        """Compare two mappings for equality."""
        if isinstance(that, PriorityDict):
            that = that._dict
        return self._dict == that

    def __ne__(self, that):
        """Compare two mappings for inequality."""
        if isinstance(that, PriorityDict):
            that = that._dict
        return self._dict != that

    def __lt__(self, that):
        """Compare two mappings for less than."""
        if isinstance(that, PriorityDict):
            that = that._dict
        _dict = self._dict
        return (_dict != that and self <= that)

    def __le__(self, that):
        """Compare two mappings for less than equal."""
        if isinstance(that, PriorityDict):
            that = that._dict
        _dict = self._dict
        return (len(_dict) <= len(that) and
                all(_dict[key] <= that[key] if key in that else False
                    for key in _dict))

    def __gt__(self, that):
        """Compare two mappings for greater than."""
        if isinstance(that, PriorityDict):
            that = that._dict
        _dict = self._dict
        return (_dict != that and self >= that)

    def __ge__(self, that):
        """Compare two mappings for greater than equal."""
        if isinstance(that, PriorityDict):
            that = that._dict
        _dict = self._dict
        return (len(_dict) >= len(that) and
                all(_dict[key] >= that[key] if key in _dict else False
                    for key in that))

    def isdisjoint(self, that):
        """
        Return True if no key in `self` is also in `that`.
        This doesn't check that the value is greater than zero.
        To remove keys with value less than or equal to zero see *clean*.
        """
        return not any(key in self for key in that)

    def items(self):
        """
        Return a list of the dictionary's items (``(key, value)``
        pairs). Items are ordered by their value from least to greatest.
        """
        return list((key, value) for value, key in self._list)

    def iteritems(self):
        """
        Return an iterable over the items (``(key, value)`` pairs) of the
        dictionary. Items are ordered by their value from least to greatest.
        """
        return iter((key, value) for value, key in self._list)

    @not26
    def viewitems(self):
        """
        In Python 2.7 and later, return a new `ItemsView` of the dictionary's
        items. Beware iterating the `ItemsView` as items are unordered.
        In Python 2.6, raise a NotImplementedError.
        """
        if hexversion < 0x03000000:
            return self._dict.viewitems()
        else:
            return self._dict.items()

    def keys(self):
        """
        Return a list of the dictionary's keys. Keys are ordered
        by their corresponding value from least to greatest.
        """
        return list(key for value, key in self._list)

    def iterkeys(self):
        """
        Return an iterable over the keys of the dictionary. Keys are ordered
        by their corresponding value from least to greatest.
        """
        return iter(key for value, key in self._list)

    @not26
    def viewkeys(self):
        """
        In Python 2.7 and later, return a new `KeysView` of the dictionary's
        keys. Beware iterating the `KeysView` as keys are unordered.
        In Python 2.6, raise a NotImplementedError.
        """
        if hexversion < 0x03000000:
            return self._dict.viewkeys()
        else:
            return self._dict.keys()

    def values(self):
        """
        Return a list of the dictionary's values. Values are
        ordered from least to greatest.
        """
        return list(value for value, key in self._list)

    def itervalues(self):
        """
        Return an iterable over the values of the dictionary. Values are
        iterated from least to greatest.
        """
        return iter(value for value, key in self._list)

    @not26
    def viewvalues(self):
        """
        In Python 2.7 and later, return a `ValuesView` of the dictionary's
        values. Beware iterating the `ValuesView` as values are unordered.
        In Python 2.6, raise a NotImplementedError.
        """
        if hexversion < 0x03000000:
            return self._dict.viewvalues()
        else:
            return self._dict.values()

    def __repr__(self):
        """Return a string representation of PriorityDict."""
        return 'PriorityDict({0})'.format(repr(dict(self)))

    def _check(self):
        self._list._check()
        assert len(self._dict) == len(self._list)
        assert all(key in self._dict and self._dict[key] == value
                   for value, key in self._list)