📄 perlfaq4.html
字号:
<HR><H3><A NAME="How_do_I_look_up_a_hash_element_">How do I look up a hash element by value?</A></H3>Create a reverse hash:<P><PRE> %by_value = reverse %by_key; $key = $by_value{$value};</PRE><P>That's not particularly efficient. It would be more space-efficient to use:<P><PRE> while (($key, $value) = each %by_key) { $by_value{$value} = $key; }</PRE><P>If your hash could have repeated values, the methods above will only findone of the associated keys. This may or may not worry you.<P><P><HR><H3><A NAME="How_can_I_know_how_many_entries_">How can I know how many entries are in a hash?</A></H3>If you mean how many keys, then all you have to do is take the scalar senseof the <CODE>keys()</CODE> function:<P><PRE> $num_keys = scalar keys %hash;</PRE><P>In void context it just resets the iterator, which is faster for tiedhashes.<P><P><HR><H3><A NAME="How_do_I_sort_a_hash_optionally">How do I sort a hash (optionally by value instead of key)?</A></H3>Internally, hashes are stored in a way that prevents you from imposing anorder on key-value pairs. Instead, you have to sort a list of the keys orvalues:<P><PRE> @keys = sort keys %hash; # sorted by key @keys = sort { $hash{$a} cmp $hash{$b} } keys %hash; # and by value</PRE><P>Here we'll do a reverse numeric sort by value, and if two keys are identical, sort by length of key, and if that fails, by straight <FONT SIZE=-1>ASCII</FONT> comparison of the keys (well, possibly modified by your locale -- see<A HREF="../../tppmsgs/msgs1.htm#105" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perllocale.html">the perllocale manpage</A>).<P><PRE> @keys = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %hash;</PRE><P><P><HR><H3><A NAME="How_can_I_always_keep_my_hash_so">How can I always keep my hash sorted?</A></H3>You can look into using the DB_File module and <CODE>tie()</CODE> using the<CODE>$DB_BTREE</CODE> hash bindings as documented in <A HREF="../../tppmsgs/msgs1.htm#108" tppabs="http://www.perl.org/CPAN/doc/manual/html/lib/DB_File.html#In_Memory_Databases">In Memory Databases</A>.<P><P><HR><H3><A NAME="What_s_the_difference_between_d">What's the difference between "delete" and "undef" with hashes?</A></H3>Hashes are pairs of scalars: the first is the key, the second is the value.The key will be coerced to a string, although the value can be any kind ofscalar: string, number, or reference. If a key <CODE>$key</CODE> is present in the array, <CODE>exists($key)</CODE> will return true. The value for a given key can be <CODE>undef</CODE>, in which case <CODE>$array{$key}</CODE> will be<CODE>undef</CODE> while <CODE>$exists{$key}</CODE> will return true. This corresponds to (<CODE>$key</CODE>, <CODE>undef</CODE>) being in the hash.<P>Pictures help... here's the <CODE>%ary</CODE> table:<P><PRE> keys values +------+------+ | a | 3 | | x | 7 | | d | 0 | | e | 2 | +------+------+</PRE><P>And these conditions hold<P><PRE> $ary{'a'} is true $ary{'d'} is false defined $ary{'d'} is true defined $ary{'a'} is true exists $ary{'a'} is true (perl5 only) grep ($_ eq 'a', keys %ary) is true</PRE><P>If you now say<P><PRE> undef $ary{'a'}</PRE><P>your table now reads:<P><PRE> keys values +------+------+ | a | undef| | x | 7 | | d | 0 | | e | 2 | +------+------+</PRE><P>and these conditions now hold; changes in caps:<P><PRE> $ary{'a'} is FALSE $ary{'d'} is false defined $ary{'d'} is true defined $ary{'a'} is FALSE exists $ary{'a'} is true (perl5 only) grep ($_ eq 'a', keys %ary) is true</PRE><P>Notice the last two: you have an undef value, but a defined key!<P>Now, consider this:<P><PRE> delete $ary{'a'}</PRE><P>your table now reads:<P><PRE> keys values +------+------+ | x | 7 | | d | 0 | | e | 2 | +------+------+</PRE><P>and these conditions now hold; changes in caps:<P><PRE> $ary{'a'} is false $ary{'d'} is false defined $ary{'d'} is true defined $ary{'a'} is false exists $ary{'a'} is FALSE (perl5 only) grep ($_ eq 'a', keys %ary) is FALSE</PRE><P>See, the whole entry is gone!<P><P><HR><H3><A NAME="Why_don_t_my_tied_hashes_make_th">Why don't my tied hashes make the defined/exists distinction?</A></H3>They may or may not implement the <CODE>EXISTS()</CODE> and <CODE>DEFINED()</CODE> methods differently. For example, there isn't the concept of undef with hashes that are tied to <FONT SIZE=-1>DBM*</FONT> files. This means the true/false tables above will give different results when used on such a hash. It also means that exists and defined do the same thing with a <FONT SIZE=-1>DBM*</FONT> file, and what they end up doing is not what they do with ordinary hashes.<P><P><HR><H3><A NAME="How_do_I_reset_an_each_operati">How do I reset an each() operation part-way through?</A></H3>Using <CODE>keys %hash</CODE> in a scalar context returns the number of keys in the hash <EM>and</EM> resets the iterator associated with the hash. You may need to do this ifyou use <CODE>last</CODE> to exit a loop early so that when you re-enter it, the hash iterator hasbeen reset.<P><P><HR><H3><A NAME="How_can_I_get_the_unique_keys_fr">How can I get the unique keys from two hashes?</A></H3>First you extract the keys from the hashes into arrays, and then solve theuniquifying the array problem described above. For example:<P><PRE> %seen = (); for $element (keys(%foo), keys(%bar)) { $seen{$element}++; } @uniq = keys %seen;</PRE><P>Or more succinctly:<P><PRE> @uniq = keys %{{%foo,%bar}};</PRE><P>Or if you really want to save space:<P><PRE> %seen = (); while (defined ($key = each %foo)) { $seen{$key}++; } while (defined ($key = each %bar)) { $seen{$key}++; } @uniq = keys %seen;</PRE><P><P><HR><H3><A NAME="How_can_I_store_a_multidimension">How can I store a multidimensional array in a DBM file?</A></H3>Either stringify the structure yourself (no fun), or else get the <FONT SIZE=-1>MLDBM</FONT> (which uses Data::Dumper) module from <FONT SIZE=-1>CPAN</FONT> and layer it on top of either DB_File or GDBM_File.<P><P><HR><H3><A NAME="How_can_I_make_my_hash_remember_">How can I make my hash remember the order I put elements into it?</A></H3>Use the Tie::IxHash from <FONT SIZE=-1>CPAN.</FONT><P><PRE> use Tie::IxHash; tie(%myhash, Tie::IxHash); for ($i=0; $i<20; $i++) { $myhash{$i} = 2*$i; } @keys = keys %myhash; # @keys = (0,1,2,3,...)</PRE><P><P><HR><H3><A NAME="Why_does_passing_a_subroutine_an">Why does passing a subroutine an undefined element in a hash create it?</A></H3>If you say something like:<P><PRE> somefunc($hash{"nonesuch key here"});</PRE><P>Then that element ``autovivifies''; that is, it springs into existencewhether you store something there or not. That's because functions getscalars passed in by reference. If <CODE>somefunc()</CODE> modifies <CODE>$_[0]</CODE>, it has to be ready to write it back into the caller's version.<P>This has been fixed as of perl5.004.<P>Normally, merely accessing a key's value for a nonexistent key does<EM>not</EM> cause that key to be forever there. This is different than awk's behavior.<P><P><HR><H3><A NAME="How_can_I_make_the_Perl_equivale">How can I make the Perl equivalent of a C structure/C++ class/hash or array of hashes or arrays?</A></H3>Use references (documented in <A HREF="../../tppmsgs/msgs0.htm#59" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlref.html">the perlref manpage</A>). Examples of complex data structures are given in <A HREF="../../tppmsgs/msgs0.htm#64" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perldsc.html">the perldsc manpage</A> and <A HREF="../../tppmsgs/msgs0.htm#63" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perllol.html">the perllol manpage</A>. Examples of structures and object-oriented classes are in <A HREF="../../tppmsgs/msgs0.htm#57" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perltoot.html">the perltoot manpage</A>.<P><P><HR><H3><A NAME="How_can_I_use_a_reference_as_a_h">How can I use a reference as a hash key?</A></H3>You can't do this directly, but you could use the standard Tie::Refhashmodule distributed with perl.<P><P><HR><H2><A NAME="Data_Misc">Data: Misc</A></H2><P><HR><H3><A NAME="How_do_I_handle_binary_data_corr">How do I handle binary data correctly?</A></H3>Perl is binary clean, so this shouldn't be a problem. For example, thisworks fine (assuming the files are found):<P><PRE> if (`cat /vmunix` =~ /gzip/) { print "Your kernel is GNU-zip enabled!\n"; }</PRE><P>On some systems, however, you have to play tedious games with ``text''versus ``binary'' files. See <A HREF="../../tppmsgs/msgs0.htm#68" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlfunc.html#binmode">binmode</A>.<P>If you're concerned about 8-bit <FONT SIZE=-1>ASCII</FONT> data, then see <A HREF="../../tppmsgs/msgs1.htm#105" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perllocale.html">the perllocale manpage</A>.<P>If you want to deal with multibyte characters, however, there are somegotchas. See the section on Regular Expressions.<P><P><HR><H3><A NAME="How_do_I_determine_whether_a_sca">How do I determine whether a scalar is a number/whole/integer/float?</A></H3>Assuming that you don't care about <FONT SIZE=-1>IEEE</FONT> notations like ``NaN'' or ``Infinity'', youprobably just want to use a regular expression.<P><PRE> warn "has nondigits" if /\D/; warn "not a whole number" unless /^\d+$/; warn "not an integer" unless /^-?\d+$/; # reject +3 warn "not an integer" unless /^[+-]?\d+$/; warn "not a decimal number" unless /^-?\d+\.?\d*$/; # rejects .2 warn "not a decimal number" unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/; warn "not a C float" unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;</PRE><P>Or you could check out <A HREF="../../tppmsgs/msgs1.htm#137" tppabs="http://www.perl.com/CPAN/modules/by-module/String/String-Scanf-1.1.tar.gz">http://www.perl.com/CPAN/modules/by-module/String/String-Scanf-1.1.tar.gz</A> instead. The <FONT SIZE=-1>POSIX</FONT> module (part of the standard Perl distribution) provides the <CODE>strtol</CODE> and <CODE>strtod</CODE> for converting strings to double and longs, respectively.<P><P><HR><H3><A NAME="How_do_I_keep_persistent_data_ac">How do I keep persistent data across program calls?</A></H3>For some specific applications, you can use one of the <FONT SIZE=-1>DBM</FONT> modules. See <A HREF="../../tppmsgs/msgs1.htm#138" tppabs="http://www.perl.org/CPAN/doc/manual/html/lib/AnyDBM_File.html">the AnyDBM_File manpage</A>. More generically, you should consult the FreezeThaw, Storable, or Class::Eroot modules from <FONT SIZE=-1>CPAN.</FONT><P><P><HR><H3><A NAME="How_do_I_print_out_or_copy_a_rec">How do I print out or copy a recursive data structure?</A></H3>The Data::Dumper module on <FONT SIZE=-1>CPAN</FONT> is nice for printing out data structures, andFreezeThaw for copying them. For example:<P><PRE> use FreezeThaw qw(freeze thaw); $new = thaw freeze $old;</PRE><P>Where <CODE>$old</CODE> can be (a reference to) any kind of data structureyou'd like. It will be deeply copied.<P><P><HR><H3><A NAME="How_do_I_define_methods_for_ever">How do I define methods for every class/object?</A></H3>Use the <FONT SIZE=-1>UNIVERSAL</FONT> class (see <A HREF="../../tppmsgs/msgs1.htm#139" tppabs="http://www.perl.org/CPAN/doc/manual/html/lib/UNIVERSAL.html">the UNIVERSAL manpage</A>).<P><P><HR><H3><A NAME="How_do_I_verify_a_credit_card_ch">How do I verify a credit card checksum?</A></H3>Get the Business::CreditCard module from <FONT SIZE=-1>CPAN.</FONT><P><P><HR><H2><A NAME="AUTHOR_AND_COPYRIGHT">AUTHOR AND COPYRIGHT</A></H2>Copyright (c) 1997 Tom Christiansen and Nathan Torkington. All rightsreserved. See <A HREF="perlfaq.html" tppabs="http://202.96.217.5/~xiaoyi/perlfaq.html">the perlfaq manpage</A> for distribution information.<P></DL> </BODY> </HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -