📄 ch05_09.htm
字号:
<HTML><HEAD><TITLE>Recipe 5.8. Inverting a Hash (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen & Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly & Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:32:44Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch05_01.htm"TITLE="5. Hashes"><LINKREL="prev"HREF="ch05_08.htm"TITLE="5.7. Hashes with Multiple Values Per Key"><LINKREL="next"HREF="ch05_10.htm"TITLE="5.9. Sorting a Hash"></HEAD><BODYBGCOLOR="#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="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch05_08.htm"TITLE="5.7. Hashes with Multiple Values Per Key"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 5.7. Hashes with Multiple Values Per Key"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch05_01.htm"TITLE="5. Hashes"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch05_10.htm"TITLE="5.9. Sorting a Hash"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 5.9. Sorting a Hash"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch05-38091">5.8. Inverting a Hash</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch05-pgfId-786">Problem <ACLASS="indexterm"NAME="ch05-idx-1000006481-0"></A><ACLASS="indexterm"NAME="ch05-idx-1000006481-1"></A></A></H3><PCLASS="para">Hashes map keys to values. You have a hash and a value for which you want to find the corresponding key.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch05-pgfId-792">Solution</A></H3><PCLASS="para">Use <CODECLASS="literal">reverse</CODE> to create an inverted hash whose values are the original hash's keys and vice versa.</P><PRECLASS="programlisting"># %LOOKUP maps keys to values%REVERSE = reverse %LOOKUP;</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch05-pgfId-802">Discussion</A></H3><PCLASS="para">This technique uses the list equivalence of hashes mentioned in the introduction. In list context, <CODECLASS="literal">reverse</CODE><ACLASS="indexterm"NAME="ch05-idx-1000006487-0"></A> treats <CODECLASS="literal">%LOOKUP</CODE> as a list and reverses the order of its elements. The significant property of a hash treated as a list is that the list elements come in pairs: the first element is the key; the second, the value. When you <CODECLASS="literal">reverse</CODE> such a list, the first element is the value, and the second is a key. Treating <EMCLASS="emphasis">this</EM> list as a hash results in a hash whose values are the keys of the original hash and vice versa.</P><PCLASS="para">Here's an example:</P><PRECLASS="programlisting">%surname = ( "Mickey" => "Mantle", "Babe" => "Ruth" );%first_name = reverse %surname;print $first_name{"Mantle"}, "\n";<CODECLASS="userinput"><B><CODECLASS="replaceable"><I>Mickey</I></CODE></B></CODE></PRE><PCLASS="para">When we treat <CODECLASS="literal">%surname</CODE> as a list, it becomes:</P><PRECLASS="programlisting">("Mickey", "Mantle", "Babe", "Ruth")</PRE><PCLASS="para">(or maybe <CODECLASS="literal">("Babe",</CODE> <CODECLASS="literal">"Ruth",</CODE> <CODECLASS="literal">"Mickey",</CODE> <CODECLASS="literal">"Mantle")</CODE> because we can't predict the order). Reversing this list gives us:</P><PRECLASS="programlisting">("Ruth", "Babe", "Mantle", "Mickey")</PRE><PCLASS="para">When we treat this list as a hash, it becomes:</P><PRECLASS="programlisting">("Ruth" => "Babe", "Mantle" => "Mickey")</PRE><PCLASS="para">Now instead of turning first names into surnames, it turns surnames into first names.</P><PCLASS="para"><ACLASS="xref"HREF="ch05_09.htm#ch05-18605"TITLE="foodfind">Example 5.2</A> is a program called <CODECLASS="literal">foodfind</CODE><ACLASS="indexterm"NAME="ch05-idx-1000006488-0"></A>. If you give it a food name, it'll tell you the color of that food. If you give it a color, it'll tell you a food of that color.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch05-18605">Example 5.2: foodfind</A></H4><PRECLASS="programlisting">#!/usr/bin/perl -w# foodfind - find match for food or color$given = shift @ARGV or die "usage: foodfind food_or_color\n";%color = ( "Apple" => "red", "Banana" => "yellow", "Lemon" => "yellow", "Carrot" => "orange" ); %food = reverse %color; if (exists $color{$given}) { print "$given is a food with color $color{$given}.\n"; } if (exists $food{$given}) { print "$food{$given} is a food with color $given.\n"; }</PRE></DIV><PCLASS="para">If two keys in the original hash have the same value (as <CODECLASS="literal">"Lemon"</CODE> and <CODECLASS="literal">"Banana"</CODE> do in the color example), then the inverted hash will only have one (which is dependent on the hashing order, and you shouldn't try to predict it). This is because hashes have, by Perl definition, unique keys.</P><PCLASS="para">If you want to invert a hash with non-unique values, you must use the techniques shown in <ACLASS="xref"HREF="ch05_08.htm"TITLE="Hashes with Multiple Values Per Key">Recipe 5.7</A>. That is, build up a hash whose values are a list of keys in the original hash:</P><PRECLASS="programlisting"># %food_color as per the introductionwhile (($food,$color) = each(%food_color)) { push(@{$foods_with_color{$color}}, $food);}print "@{$foods_with_color{yellow}} were yellow foods.\n";<CODECLASS="userinput"><B><CODECLASS="replaceable"><I>Banana Lemon were yellow foods.</I></CODE></B></CODE></PRE><PCLASS="para">This also lets us change the <CODECLASS="literal">foodfind</CODE> program to handle colors represented by more than one food. For instance, <CODECLASS="literal">foodfind</CODE> <CODECLASS="literal">yellow</CODE> reports bananas and lemons.</P><PCLASS="para">If any values in the original hash were references instead of just strings and numbers, the inverted hash poses a problem because references don't work well as hash keys unless you use the Tie::RefHash module described in <ACLASS="xref"HREF="ch05_13.htm"TITLE="Hashing References">Recipe 5.12</A>.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch05-pgfId-894">See Also</A></H3><PCLASS="para">The <CODECLASS="literal">reverse</CODE> function in <ICLASS="filename">perlfunc </I>(1) and in <ACLASS="olink"HREF="../prog/ch03_01.htm">Chapter 3</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A>; <ACLASS="xref"HREF="ch13_16.htm"TITLE="Creating Magic Variables with tie">Recipe 13.15</A> <ACLASS="indexterm"NAME="ch05-idx-1000006483-0"></A><ACLASS="indexterm"NAME="ch05-idx-1000006483-1"></A></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch05_08.htm"TITLE="5.7. Hashes with Multiple Values Per Key"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 5.7. Hashes with Multiple Values Per Key"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch05_10.htm"TITLE="5.9. Sorting a Hash"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 5.9. Sorting a Hash"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">5.7. Hashes with Multiple Values Per Key</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">5.9. Sorting a Hash</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright © 2002</a> O'Reilly & 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 + -