⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch05_03.htm

📁 by Randal L. Schwartz and Tom Phoenix ISBN 0-596-00132-0 Third Edition, published July 2001. (See
💻 HTM
字号:
<html><head><title>Hash Functions (Learning Perl, 3rd Edition)</title><link rel="stylesheet" type="text/css" href="../style/style1.css" /><meta name="DC.Creator" content="Randal L. Schwartz and Tom Phoenix" /><meta name="DC.Format" content="text/xml" scheme="MIME" /><meta name="DC.Language" content="en-US" /><meta name="DC.Publisher" content="O'Reilly &amp; Associates, Inc." /><meta name="DC.Source" scheme="ISBN" content="0596001320L" /><meta name="DC.Subject.Keyword" content="stuff" /><meta name="DC.Title" content="Learning Perl, 3rd Edition" /><meta name="DC.Type" content="Text.Monograph" /></head><body bgcolor="#ffffff"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Learning Perl, 3rd Edition" /><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch05_02.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"></a></td><td align="right" valign="top" width="228"><a href="ch05_04.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr></table></div><h2 class="sect1">5.3. Hash Functions</h2><p><a name="INDEX-403" /> <a name="INDEX-404" />Naturally, there are some usefulfunctions that can work on an entire hash at once.</p><a name="lperl3-CHP-5-SECT-3.1" /><div class="sect2"><h3 class="sect2">5.3.1. The keys and values Functions</h3><p>The <tt class="literal">keys</tt><a name="INDEX-405" /> function yields a list of all thecurrent keys in a hash, while the<tt class="literal">values</tt><a name="INDEX-406" /> function gives the correspondingvalues. If there are no elements to the hash, then either functionreturns an empty list:</p><blockquote><pre class="code">my %hash = ("a" =&gt; 1, "b" =&gt; 2, "c" =&gt; 3);my @k = keys %hash;my @v = values %hash;</pre></blockquote><p>So, <tt class="literal">@k</tt> will contain <tt class="literal">"a"</tt>,<tt class="literal">"b"</tt>, and <tt class="literal">"c"</tt>, and<tt class="literal">@v</tt> will contain <tt class="literal">1</tt>,<tt class="literal">2</tt>, and <tt class="literal">3</tt> -- in<em class="emphasis">some</em> order. Remember, Perl doesn'tmaintain the order of elements in a hash. But, whatever order thekeys are in, the values will be in the corresponding order: If<tt class="literal">"b"</tt> is last in the keys, <tt class="literal">2</tt> willbe last in the values; if <tt class="literal">"c"</tt> is the first key,<tt class="literal">3</tt> will be the first value. That's true aslong as you don't modify the hash between the request for thekeys and the one for the values. If you add elements to the hash,Perl reserves the right to rearrange it as needed, to keep the accessquick.<a href="#FOOTNOTE-131">[131]</a></p><blockquote class="footnote"> <a name="FOOTNOTE-131" /><p>[131]Of course, if you started adding elements tothe hash between <tt class="literal">keys</tt> and<tt class="literal">values</tt>, your list of values (or keys, whicheveryou did second) would have additional items, which would be tough tomatch up with the first list. So no normal programmer would do that.</p> </blockquote><p>In a scalar context, these functions give the number of elements(key-value pairs) in the hash. They do this quite efficiently,without having to visit each element of the hash:</p><blockquote><pre class="code">my $count = keys %hash;  # gets 3, meaning three key-value pairs</pre></blockquote><p>Once in a long while, you'll see that someone has used a hashas a Boolean (true/false) expression, something like this:</p><blockquote><pre class="code">if (%hash) {  print "That was a true value!\n";}</pre></blockquote><p>That will be true if (and only if) the hash has at least onekey-value pair.<a href="#FOOTNOTE-132">[132]</a> So,it's just saying, "if the hash is not empty...".But this is a pretty rare construct, as such things go.</p><blockquote class="footnote"> <a name="FOOTNOTE-132" /><p>[132]The actual result is an internaldebugging string useful to the people who maintain Perl. It lookssomething like "4/16", but the value is guaranteed to betrue when the hash is non-empty, and false when it's empty, sothe rest of us can still use it for that.</p> </blockquote></div><a name="lperl3-CHP-5-SECT-3.2" /><div class="sect2"><h3 class="sect2">5.3.2. The each Function</h3><p>If you wish to iterate over (that is, examine every element of) anentire hash, one of the usual ways is to use the<tt class="literal">each</tt><a name="INDEX-407" /> function, which returns a key-valuepair as a two-element list.<a href="#FOOTNOTE-133">[133]</a> On each evaluation of this function forthe same array, the next successive key-value pair is returned, untilall the elements have been accessed. When there are no more pairs,<tt class="literal">each</tt> returns an empty list.</p><blockquote class="footnote"> <a name="FOOTNOTE-133" /><p>[133]The other usual way toiterate over an entire hash is to use <tt class="literal">foreach</tt> on alist of keys from the hash; we'll see that by the end of thissection.</p> </blockquote><p>In practice, the only way to use <tt class="literal">each</tt> is in a<tt class="literal">while</tt><a name="INDEX-408" /> loop, something like this:</p><blockquote><pre class="code">while ( ($key, $value) = each %hash ) {  print "$key =&gt; $value\n";}</pre></blockquote><p>There's a lot going on here. First, <tt class="literal">each%hash</tt> returns a key-value pair from the hash, as atwo-element list; let's say that the key is<tt class="literal">"c"</tt> and the value is <tt class="literal">3</tt>, so thelist is <tt class="literal">("c", 3)</tt>. That list is assigned to thelist <tt class="literal">($key,</tt> <tt class="literal">$value)</tt>, so<tt class="literal">$key</tt> becomes <tt class="literal">"c"</tt>, and<tt class="literal">$value</tt> becomes <tt class="literal">3</tt>.</p><p>But that list assignment is happening in the conditional expressionof the <tt class="literal">while</tt> loop, which is a scalar context.(Specifically, it's a Boolean context, looking for a true/falsevalue; and a Boolean context is a particular kind of scalar context.)The value of a list assignment in a scalar context is the number ofelements in the source list -- <tt class="literal">2</tt>, in this case.Since <tt class="literal">2</tt> is a true value, we enter the body of theloop and print the message <tt class="literal">c =&gt; 3</tt>.</p><p>The next time through the loop, <tt class="literal">each %hash</tt> gives anew key-value pair; let's say it's <tt class="literal">("a",1)</tt> this time. (It knows to return a different pair thanpreviously because it keeps track of where it is; in technicaljargon, there's an iterator stored in with each hash.<a href="#FOOTNOTE-134">[134]</a>) Those two items are stored into <tt class="literal">($key,$value)</tt>. Since the number of elements in the source listwas again <tt class="literal">2</tt>, a true value, the<tt class="literal">while</tt> condition is true, and the loop body runsagain, telling us <tt class="literal">a =&gt; 1</tt>.</p><blockquote class="footnote"><a name="FOOTNOTE-134" /><p>[134]Since each hash has its own private iterator, loops using<tt class="literal">each </tt>may be nested, as long as they areiterating over <em class="emphasis">different</em> hashes. And, as long aswe're already in a footnote, we may as well tell you:it's unlikely you'll ever need to do so, but you mayreset the iterator of a hash by using the <tt class="literal">keys</tt>or <tt class="literal">values</tt> function on the hash. Theiterator is also automatically reset if a new list is stored into theentire hash, or if <tt class="literal">each </tt>has iterated through allof the items to the "end" of the hash. On the other hand,adding new key-value pairs to the hash while iterating over it isgenerally a bad idea, since that won't necessarily reset theiterator. That's likely to confuse you, your maintenanceprogrammer, and <tt class="literal">each </tt>as well.</p></blockquote><p>We go one more time through the loop, and by now we know what toexpect, so it's no surprise to see <tt class="literal">b =&gt; 2</tt>appear in the output.</p><p>But we knew it couldn't go on forever. Now, when Perl evaluates<tt class="literal">each %hash</tt>, there are no more key-value pairsavailable. So, <tt class="literal">each</tt> has to return an emptylist.<a href="#FOOTNOTE-135">[135]</a> The empty list is assigned to <tt class="literal">($key,$value)</tt>, so <tt class="literal">$key</tt> gets<tt class="literal">undef</tt>, and <tt class="literal">$value</tt> also gets<tt class="literal">undef</tt>.</p><blockquote class="footnote"> <a name="FOOTNOTE-135" /><p>[135]It's being used in list context, so itcan't return <tt class="literal">undef</tt> to signal failure; thatwould be the one-element list <tt class="literal">(undef)</tt>instead ofthe empty (zero-element) list <tt class="literal">( )</tt>. </p></blockquote><p>But that hardly matters, because the whole thing is being evaluatedin the conditional expression of the <tt class="literal">while</tt> loop.The value of a list assignment in a scalar context is the number ofelements in the source list -- in this case, that's<tt class="literal">0</tt>. Since <tt class="literal">0</tt> is a false value,the <tt class="literal">while</tt> loop is done, and execution continueswith the rest of the program.</p><p>Of course, <tt class="literal">each</tt> returns the key-value pairs in ajumbled order. (It's the same order as<tt class="literal">keys</tt> and <tt class="literal">values</tt> would give,incidentally; the "natural" order of the hash.) If youneed to go through the hash in order, simply sort the keys, perhapssomething like this:</p><blockquote><pre class="code">foreach $key (sort keys %hash) {  $value = $hash{$key};  print "$key =&gt; $value\n";  # Or, we could have avoided the extra $value variable:  #  print "$key =&gt; $hash{$key}\n";}</pre></blockquote><p>We'll see more about sorting hashes in <a href="ch15_01.htm">Chapter 15, "Strings and Sorting"</a>.<a name="INDEX-409" /> <a name="INDEX-410" /> </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_02.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_04.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr><tr><td align="left" valign="top" width="228">5.2. Hash Element Access</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.4. Typical Use of a Hash</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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -