ch05_02.htm

来自「by Randal L. Schwartz and Tom Phoenix I」· HTM 代码 · 共 315 行 · 第 1/2 页

HTM
315
字号
item quickly. So you'd normally use a hash either when youdon't care what order the items are in, or when you have aneasy way to put them into the order you want.</p><p>Of course, even though the order of the key-value pairs is jumbled,each key "sticks" with its corresponding value in theresulting list. So, even though we don't know where the key<tt class="literal">foo</tt> will appear in the list, we know that itsvalue, <tt class="literal">35</tt>, will be right after it.</p></div><a name="lperl3-CHP-5-SECT-2.2" /><div class="sect2"><h3 class="sect2">5.2.2. Hash Assignment</h3><p><a name="INDEX-392" /><a name="INDEX-393" />It'srare to do so, but a hash may be copied using the obvious syntax:</p><blockquote><pre class="code">%new_hash = %old_hash;</pre></blockquote><p>This is actually more work for Perl than meets the eye. Unlike whathappens in languages like Pascal or C, where such an operation wouldbe a simple matter of copying a block of memory, Perl's datastructures are more complex. So, that line of code tells Perl tounwind the <tt class="literal">%old_hash</tt> into a list of key-valuepairs, then assign those to <tt class="literal">%new_hash</tt>, building itup one key-value pair at a time.</p><p>It's more common to transform the hash in some way, though. Forexample, we could make an inverse hash:</p><blockquote><pre class="code">%inverse_hash = reverse %any_hash;</pre></blockquote><p>This takes <tt class="literal">%any_hash</tt> and unwinds it into a list ofkey-value pairs, making a list like<tt class="literal">(</tt><em class="emphasis">key</em>,<em class="emphasis">value</em>, <em class="emphasis">key</em>,<em class="emphasis">value</em>, <em class="emphasis">key</em>,<em class="emphasis">value</em>, ...<tt class="literal">)</tt>. Then<tt class="literal">reverse</tt> turns that list end-for-end, making a listlike <tt class="literal">(</tt><em class="emphasis">value</em>,<em class="emphasis">key</em>, <em class="emphasis">value</em>,<em class="emphasis">key</em>, <em class="emphasis">value</em>,<em class="emphasis">key</em>, ...<tt class="literal">)</tt>. Now the keys arewhere the values used to be, and the values are where the keys usedto be. When that's stored into<tt class="literal">%inverse_hash</tt>, we'll be able to look up astring that was a value in<tt class="literal">%any_hash</tt> -- it's now a key of<tt class="literal">%inverse_hash</tt>. And the value we'll find isone that was one of the keys from <tt class="literal">%any_hash</tt>. So,we have a way to look up a "value" (now a key), and finda "key" (now a value).</p><p>Of course, you might guess (or determine from scientific principles,if you're clever) that this will work properly only if thevalues in the original hash were unique -- otherwise we'dhave duplicate keys in the new hash, and keys are always unique.Here's the rule that Perl uses: the last one in wins. That is,the later items in the list overwrite any earlier ones. Of course, wedon't know what order the key-value pairs will have in thislist, so there's no telling which ones would win. You'duse this technique only if you know there are no duplicates among theoriginal values.<a href="#FOOTNOTE-128">[128]</a> But that's the case for the IP address and hostname examples given earlier:</p><blockquote class="footnote"> <a name="FOOTNOTE-128" /><p>[128]Or if you don't care thatthere are duplicates. For example, we could invert the<tt class="literal">%family_name</tt> hash (in which the keys arepeople's given names and values are their family names) to makeit easy to determine whether there is or is not anyone with a givenfamily name in the group. Thus, in the inverted hash, ifthere's no key of <tt class="literal">slate</tt>, we'd knowthat there's no one with that name in the original hash.</p></blockquote><blockquote><pre class="code">%ip_address = reverse %host_name;</pre></blockquote><p>Now we can look up a host name or IP address with equal ease, to findthe corresponding IP address or host name.</p></div><a name="lperl3-CHP-5-SECT-2.3" /><div class="sect2"><h3 class="sect2">5.2.3. The Big Arrow</h3><p><a name="INDEX-394" /><a name="INDEX-395" /><a name="INDEX-396" />When assigning a listto a hash, sometimes it's not obvious which elements are keysand which are values. For example, in this assignment (which we sawearlier), we humans have to count through the list, saying,"key, value, key, value...", in order to determinewhether <tt class="literal">2.5</tt> is a key or a value:</p><blockquote><pre class="code">%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",      "wilma", 1.72e30, "betty", "bye\n");</pre></blockquote><p>Wouldn't it be nice if Perl gave us a way to pair up keys andvalues in that kind of a list, so that it would be easy to see whichones were which? Larry thought so, too, which is why he invented thebig arrow, (<tt class="literal">=&gt;</tt>).<a href="#FOOTNOTE-129">[129]</a> To Perl, it'sjust a different way to "spell" a comma. That is, in thePerl grammar, any time that you need a <a name="INDEX-399" /> <a name="INDEX-400" />comma ( <tt class="literal">,</tt> ), you canuse the big arrow instead; it's all the same to Perl.<a href="#FOOTNOTE-130">[130]</a> So here's another way to set up the hash of lastnames:</p><blockquote class="footnote"> <a name="FOOTNOTE-129" /><p>[129]Yes,there's also a <em class="emphasis">little</em><a name="INDEX-397" /> <a name="INDEX-398" />arrow, (<tt class="literal">-&gt;</tt>).It's used with references, which are an advanced topic; see the<em class="emphasis">perlreftut</em>and<em class="emphasis">perlref</em>manpage whenyou're ready for that.</p> </blockquote><blockquote class="footnote"><a name="FOOTNOTE-130" /><p>[130]Well, there's one technical difference: any bareword (asequence of nothing but letters, digits, and underscores not startingwith a digit) to the left of the big arrow is implicitly quoted. Soyou can leave off the quote marks on a bareword to the left of thebig arrow. You may also omit the quote marks if there's nothingbut a bareword as a key inside the curly braces of a hash.</p></blockquote><blockquote><pre class="code">my %last_name = (  # a hash may be a lexical variable  "fred" =&gt; "flintstone",  "dino" =&gt; undef,  "barney" =&gt; "rubble",  "betty" =&gt; "rubble",);</pre></blockquote><p>Here, it's easy (or perhaps at least easier) to see whose namepairs with which value, even if we end up putting many pairs on oneline. And notice that there's an extra comma at the end of thelist. As we saw earlier, this is harmless, but convenient; if we needto add additional people to this hash, we'll simply make surethat each line has a key-value pair and a trailing comma. Perl willsee that there is a comma between each item and the next, and oneextra (harmless) comma at the end of the list.<a name="INDEX-401" /> <a name="INDEX-402" /></p></div><hr width="684" align="left" /><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch05_01.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"><img alt="Home" border="0" src="../gifs/txthome.gif" /></a></td><td align="right" valign="top" width="228"><a href="ch05_03.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr><tr><td align="left" valign="top" width="228">5. Hashes</td><td align="center" valign="top" width="228"><a href="index/index.htm"><img alt="Book Index" border="0" src="../gifs/index.gif" /></a></td><td align="right" valign="top" width="228">5.3. Hash Functions</td></tr></table></div><hr width="684" align="left" /><img alt="Library Navigation Links" border="0" src="../gifs/navbar.gif" usemap="#library-map" /><p><p><font size="-1"><a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font></p><map name="library-map"><area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map></body></html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?