Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The only problem with <code>heapq</code> is that it doesn't provide a <code>key</code> function like everything else in the stdlib does. (If you're curious why, Raymond Hettinger explains in <a href="http://code.activestate.com/lists/python-list/162387/" rel="noreferrer">this email</a>. He's right that <code>heapq</code> couldn't provide the same interface as other sort functions—but the reasons don't affect your use case, where <code>key</code> would just be <code>lambda x: -x</code>.)</p> <p>The usual workaround is to decorate-heap-undecorate. That is, put a modified version of your values into the heap that sorts by <code>key</code>. Normally, this means one of the following:</p> <ul> <li>Storing <code>key(x)</code> instead of <code>x</code>, and then accessing <code>unkey(value)</code> instead of <code>value</code> (assuming <code>key</code> is reversible).</li> <li>Storing <code>(key(x), x)</code> instead of <code>x</code>, and then accessing <code>value[1]</code>. (This can break stability, but <code>heapq</code> doesn't promise stability anyway.)</li> <li>Writing a wrapper class that implements a custom <code>__le__</code> method, then storing <code>Wrapper(x)</code> instead of <code>x</code> and accessing <code>value.value</code> instead of <code>value</code>.</li> </ul> <p>In your case, the key function is reversible. So, just store <code>-x</code>, and access <code>-value</code>. That's about as trivial as decoration gets.</p> <p>Still, regardless of how simple it is, you should probably write a wrapper, or you will screw it up at some point. For example, you could write a <code>maxheap</code> that wraps the minheap in <code>heapq</code> like this:</p> <pre><code>import heapq def heapify(x): for i in range(len(x)): x[i] = -x[i] heapq.heapify(x) def heappush(heap, item): heapq.heappush(heap, -item) def heappop(heap): return -heapq.heappop(heap) </code></pre> <p>… and so on for any other functions you need. It may be a bit of a pain, but it's a lot less work than implementing the whole thing from scratch.</p> <p>While you're at it, you may want to wrap the heap in an object-oriented API so you can do <code>heap.push(x)</code> instead of <code>heapq.heappush(heap, x)</code>, etc.</p> <pre><code>import heapq class MaxHeap(object): def __init__(self, x): self.heap = [-e for e in x] heapq.heapify(self.heap) def push(self, value): heapq.heappush(self.heap, -value) def pop(self): return -heapq.heappop(self.heap) </code></pre> <p>…</p> <p>If you take a quick look around the recipes at ActiveState or the modules on PyPI, you should find that others have already done most of the work for you.</p> <p>Alternatively, you could copy and paste the <code>heapq</code> source (it's pure Python) as <code>maxheapq.py</code> and just replace the <code>cmp_lt</code> function with its opposite. (Of course if you're doing that, it's probably just as easy, and certainly a lot clearer, to modify <code>cmp_lt</code> to take a <code>key</code> argument in the first place, and modify all the other functions to pass the <code>key</code> through—bearing in mind that it won't be as generally applicable anymore, because it can't make the usual guarantee that <code>key</code> is only called once.)</p> <p>If you really want to live dangerously (you shouldn't), you could even monkeypatch it:</p> <pre><code>import heapq def cmp_gt(x, y): return y &lt; x if hasattr(y, '__lt__') else not (x &lt;= y) heapq.cmp_lt = cmp_gt </code></pre> <p>But you don't want to do that in real code.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload