uTools-Manuals/docs/python/bisect.html
2019-04-21 11:50:48 +08:00

52 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="body" role="main"><div class="section" id="module-bisect"><h1><span class="yiyi-st" id="yiyi-10">8.6. <a class="reference internal" href="#module-bisect" title="bisect: Array bisection algorithms for binary searching."><code class="xref py py-mod docutils literal"><span class="pre">bisect</span></code></a> - 数组对分算法</span></h1><p><span class="yiyi-st" id="yiyi-11"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/bisect.py">Lib / bisect.py</a></span></p><p><span class="yiyi-st" id="yiyi-12">此模块支持以排序顺序维护列表,而不必在每次插入后对列表进行排序。</span><span class="yiyi-st" id="yiyi-13">对于具有昂贵的比较操作的项目的长列表,这可以是对更常见的方法的改进。</span><span class="yiyi-st" id="yiyi-14">该模块称为<a class="reference internal" href="#module-bisect" title="bisect: Array bisection algorithms for binary searching."><code class="xref py py-mod docutils literal"><span class="pre">bisect</span></code></a>,因为它使用基本对分算法来完成其工作。</span><span class="yiyi-st" id="yiyi-15">源代码作为算法的工作示例可能是最有用的(边界条件已经是对的!</span><span class="yiyi-st" id="yiyi-16">)。</span></p><p><span class="yiyi-st" id="yiyi-17">提供以下功能:</span></p><dl class="function"><dt id="bisect.bisect_left"><span class="yiyi-st" id="yiyi-18"><code class="descclassname">bisect.</code><code class="descname">bisect_left</code><span class="sig-paren">(</span><em>a</em>, <em>x</em>, <em>lo=0</em>, <em>hi=len(a)</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-19"><em>a</em>中找到<em>x</em>的插入点以保持排序顺序。</span><span class="yiyi-st" id="yiyi-20">参数<em>lo</em><em>hi</em>可以用于指定应该考虑的列表的子集;默认情况下使用整个列表。</span><span class="yiyi-st" id="yiyi-21">如果<em>x</em>已存在于<em>a</em>中,则插入点将在任何现有条目之前(左侧)。</span><span class="yiyi-st" id="yiyi-22">返回值适合用作<code class="docutils literal"><span class="pre">list.insert()</span></code>的第一个参数,假设<em>a</em>已经排序。</span></p><p><span class="yiyi-st" id="yiyi-23">返回的插入点<em>i</em>将数组<em>a</em>分成两半,使得<code class="docutils literal"><span class="pre">allval</span> <span class="pre"> <span class="pre">x</span> <span class="pre">for</span> <span class="pre">val</span> <span class="pre">in</span> <span class="pre">a [loi]</span> 对于<span class="pre"><code class="docutils literal"><span class="pre">allval</span> <span class="pre">&gt; =</span> <span class="pre">x</span> <span class="pre">t15&gt; <span class="pre">in</span> <span class="pre">a [ihi]</span></span></code></span></span></code></span></p></dd></dl><dl class="function"><dt id="bisect.bisect_right"><span class="yiyi-st" id="yiyi-24"><code class="descclassname">bisect.</code><code class="descname">bisect_right</code><span class="sig-paren">(</span><em>a</em>, <em>x</em>, <em>lo=0</em>, <em>hi=len(a)</em><span class="sig-paren">)</span></span></dt><dt id="bisect.bisect"><span class="yiyi-st" id="yiyi-25"> <code class="descclassname">bisect.</code><code class="descname">bisect</code><span class="sig-paren">(</span><em>a</em>, <em>x</em>, <em>lo=0</em>, <em>hi=len(a)</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-26">类似于<a class="reference internal" href="#bisect.bisect_left" title="bisect.bisect_left"><code class="xref py py-func docutils literal"><span class="pre">bisect_left()</span></code></a>,但返回在<em>a</em><em>x</em>的任何现有条目之后(右侧)的插入点。</span></p><p><span class="yiyi-st" id="yiyi-27">The returned insertion point <em>i</em> partitions the array <em>a</em> into two halves so that <code class="docutils literal"><span class="pre">all(val</span> <span class="pre">&lt;=</span> <span class="pre">x</span> <span class="pre">for</span> <span class="pre">val</span> <span class="pre">in</span> <span class="pre">a[lo:i])</span></code> for the left side and <code class="docutils literal"><span class="pre">all(val</span> <span class="pre">&gt;</span> <span class="pre">x</span> <span class="pre">for</span> <span class="pre">val</span> <span class="pre">in</span> <span class="pre">a[i:hi])</span></code> for the right side.</span></p></dd></dl><dl class="function"><dt id="bisect.insort_left"><span class="yiyi-st" id="yiyi-28"><code class="descclassname">bisect.</code><code class="descname">insort_left</code><span class="sig-paren">(</span><em>a</em>, <em>x</em>, <em>lo=0</em>, <em>hi=len(a)</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-29">以排序顺序在<em>a</em>中插入<em>x</em></span><span class="yiyi-st" id="yiyi-30">这相当于<code class="docutils literal"><span class="pre">a.insertbisect.bisect_lefta</span> <span class="pre">x</span> <span class="pre">lo</span> <span class="pre">hi t4&gt; <span class="pre">x</span></span></code>,假设<em>a</em>已经排序。</span><span class="yiyi-st" id="yiyi-31">请记住Olog n搜索由缓慢的On插入步骤控制。</span></p></dd></dl><dl class="function"><dt id="bisect.insort_right"><span class="yiyi-st" id="yiyi-32"><code class="descclassname">bisect.</code><code class="descname">insort_right</code><span class="sig-paren">(</span><em>a</em>, <em>x</em>, <em>lo=0</em>, <em>hi=len(a)</em><span class="sig-paren">)</span></span></dt><dt id="bisect.insort"><span class="yiyi-st" id="yiyi-33"><code class="descclassname">bisect.</code><code class="descname">insort</code><span class="sig-paren">(</span><em>a</em>, <em>x</em>, <em>lo=0</em>, <em>hi=len(a)</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-34">类似于<a class="reference internal" href="#bisect.insort_left" title="bisect.insort_left"><code class="xref py py-func docutils literal"><span class="pre">insort_left()</span></code></a>,但在<em>x</em>的任何现有条目后在<em>a</em>中插入<em>x</em></span></p></dd></dl><div class="admonition seealso"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-35">也可以看看</span></p><p class="last"><span class="yiyi-st" id="yiyi-36"><a class="reference external" href="https://code.activestate.com/recipes/577197-sortedcollection/">SortedCollection食谱</a>使用bisect通过直接搜索方法构建一个全功能的容器类并支持键功能。</span><span class="yiyi-st" id="yiyi-37">密钥预先计算以在搜索期间节省对密钥功能的不必要的调用。</span></p></div><div class="section" id="searching-sorted-lists"><h2><span class="yiyi-st" id="yiyi-38">8.6.1.</span><span class="yiyi-st" id="yiyi-39">搜索排序列表</span></h2><p><span class="yiyi-st" id="yiyi-40">The above <a class="reference internal" href="#module-bisect" title="bisect: Array bisection algorithms for binary searching."><code class="xref py py-func docutils literal"><span class="pre">bisect()</span></code></a> functions are useful for finding insertion points but can be tricky or awkward to use for common searching tasks.</span><span class="yiyi-st" id="yiyi-41">以下五个函数显示如何将它们转换为排序列表的标准查找:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="s1">'Locate the leftmost value exactly equal to x'</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">bisect_left</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="ow">and</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">x</span><span class="p">:</span>
<span class="k">return</span> <span class="n">i</span>
<span class="k">raise</span> <span class="ne">ValueError</span>
<span class="k">def</span> <span class="nf">find_lt</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="s1">'Find rightmost value less than x'</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">bisect_left</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="k">if</span> <span class="n">i</span><span class="p">:</span>
<span class="k">return</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">raise</span> <span class="ne">ValueError</span>
<span class="k">def</span> <span class="nf">find_le</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="s1">'Find rightmost value less than or equal to x'</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">bisect_right</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="k">if</span> <span class="n">i</span><span class="p">:</span>
<span class="k">return</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">raise</span> <span class="ne">ValueError</span>
<span class="k">def</span> <span class="nf">find_gt</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="s1">'Find leftmost value greater than x'</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">bisect_right</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
<span class="k">return</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="k">raise</span> <span class="ne">ValueError</span>
<span class="k">def</span> <span class="nf">find_ge</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="s1">'Find leftmost item greater than or equal to x'</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">bisect_left</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
<span class="k">return</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="k">raise</span> <span class="ne">ValueError</span>
</code></pre></div><div class="section" id="other-examples"><h2><span class="yiyi-st" id="yiyi-42">8.6.2.</span><span class="yiyi-st" id="yiyi-43">其他示例</span></h2><p id="bisect-example"><span class="yiyi-st" id="yiyi-44"><a class="reference internal" href="#module-bisect" title="bisect: Array bisection algorithms for binary searching."><code class="xref py py-func docutils literal"><span class="pre">bisect()</span></code></a>函数可用于数值表查找。</span><span class="yiyi-st" id="yiyi-45">本示例使用<a class="reference internal" href="#module-bisect" title="bisect: Array bisection algorithms for binary searching."><code class="xref py py-func docutils literal"><span class="pre">bisect()</span></code></a>根据一组有序数字断点查找考试成绩的字母分数90向上为“A”80至89为“ B',等等:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">grade</span><span class="p">(</span><span class="n">score</span><span class="p">,</span> <span class="n">breakpoints</span><span class="o">=</span><span class="p">[</span><span class="mi">60</span><span class="p">,</span> <span class="mi">70</span><span class="p">,</span> <span class="mi">80</span><span class="p">,</span> <span class="mi">90</span><span class="p">],</span> <span class="n">grades</span><span class="o">=</span><span class="s1">'FDCBA'</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">i</span> <span class="o">=</span> <span class="n">bisect</span><span class="p">(</span><span class="n">breakpoints</span><span class="p">,</span> <span class="n">score</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">grades</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">grade</span><span class="p">(</span><span class="n">score</span><span class="p">)</span> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">33</span><span class="p">,</span> <span class="mi">99</span><span class="p">,</span> <span class="mi">77</span><span class="p">,</span> <span class="mi">70</span><span class="p">,</span> <span class="mi">89</span><span class="p">,</span> <span class="mi">90</span><span class="p">,</span> <span class="mi">100</span><span class="p">]]</span>
<span class="go">['F', 'A', 'C', 'C', 'B', 'A', 'A']</span>
</code></pre><p><span class="yiyi-st" id="yiyi-46"><a class="reference internal" href="functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal"><span class="pre">sorted()</span></code></a>函数不同的是,<a class="reference internal" href="#module-bisect" title="bisect: Array bisection algorithms for binary searching."><code class="xref py py-func docutils literal"><span class="pre">bisect()</span></code></a>函数具有<em></em><em>颠倒 t7 &gt;因为这会导致设计效率低下(连续调用平分函数不会“记住”以前的所有键查找)。</em></span></p><p><span class="yiyi-st" id="yiyi-47">相反,最好搜索预先计算的密钥列表以查找有问题的记录的索引:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'yellow'</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="p">(</span><span class="s1">'black'</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">r</span><span class="p">:</span> <span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span><span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">data</span><span class="p">]</span> <span class="c1"># precomputed list of keys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="p">[</span><span class="n">bisect_left</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]</span>
<span class="go">('black', 0)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="p">[</span><span class="n">bisect_left</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
<span class="go">('blue', 1)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="p">[</span><span class="n">bisect_left</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="mi">5</span><span class="p">)]</span>
<span class="go">('red', 5)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="p">[</span><span class="n">bisect_left</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="mi">8</span><span class="p">)]</span>
<span class="go">('yellow', 8)</span>
</code></pre></div></div></div>