extern: index
intern: preamble | hash | reference | sample | copy hash | modify | delete | end
A Perl HASH, or 'associative array', is a FASCINATING beast ... and this page contains some example ...
To declare a hash, use '%', and to clear the hash ...
code:
my %hash1 = ();
To declare a hash with elements ... I always think of it as a 'key' pointing to a 'value' ...
code:
my %hash1 = ( 'key1' => 'key1 Value', 'key2' => 'key2 Value', 'key3' => 'key3 Value' );
To get the count of elements in a hash ...
code:
my $cnt = scalar keys %hash1; print "Got $cnt keys in \%hash1 ...\n";
output:
Got 3 keys in %hash1 ...
To enumerate the keys, and values, you can use the following ... note the use of the scalar '$' and the curly brackets, { } ... also note the order is not necessarily as declared! ...
code:
foreach my $key (keys %hash1 ) { print $key.' has value ['. $hash1{$key} ."]\n"; }
output:
key2 has value [key2 Value] key1 has value [key1 Value] key3 has value [key3 Value]
To establish some order, the array of keys returned by 'keys %hash1' can be sorted ...
code:
my @arr = keys %hash1; foreach my $key ( sort @arr ) { print $key.' has value ['. $hash1{$key} ."]\n"; }
output:
key1 has value [key1 Value] key2 has value [key2 Value] key3 has value [key3 Value]
Another example - With a HASH, like the following, with the subs shown, and then a test output ... Note the return of a hash reference, and how the members of that hash reference can be accessed ...
code:
#!/Perl # testiso2.pl - 2006.08.28 # ISO' => 'Country' my %CurrencyISO = ( 'AED' => 'United Arab Emirates Dirhams', 'AUD' => 'Australia Dollars', 'AWG' => 'Aruba Guilders', 'BBD' => 'Barbados Dollars', 'BMD' => 'Bermuda Dollars' ); print "test ISO to Currency ...\n"; print "ISO AWG = ".ISO2Currency('AWG')."\n"; print "test Currency to ISO ...\n"; my $ref_test = Currency2ISO('dollar'); my $cnt = keys %$ref_test; if ($cnt) { while (my ($k, $v) = each %$ref_test) { print "ISO [$k] => [$v]\n"; } } else { print "FAILED\n"; } exit(0); sub ISO2Currency { my ($iso) = shift; my $v = ''; foreach my $k (keys %CurrencyISO) { if ($k eq $iso) { $v = $CurrencyISO{$k}; return $v; } } return "NOT FOUND $iso"; } sub Currency2ISO { my ($cur) = shift; my %aa = (); my $v = ''; foreach my $k (keys %CurrencyISO) { $v = $CurrencyISO{$k}; if ($v =~ /$cur/i) { ###print "Added [$k] [$v]\n"; $aa{$k} = $v; } } return \%aa; # return a reference } # end testiso2.pl
output:
test ISO to Currency ... ISO AWG = Aruba Guilders test Currency to ISO ... ISO [BBD] => [Barbados Dollars] ISO [AUD] => [Australia Dollars] ISO [BMD] => [Bermuda Dollars]
Then there are times we might want the HASH to contains references to anonymous arrays, like - note the special [...] notation to cause a COPY of the array to be stored in the HASH ...
code:
#!/Perl # Sometimes we may want a hash to contain a COPY of an array (as a reference) # and NOT refer back to the original array variable. my %hash = (); my ($aref); my $conf1 = 'proj|Debug'; my $conf2 = 'proj|Release'; my $item1 = 'defines=[/D "NDEBUG"]'; my $item2 = 'outputs=[".\Release"]'; my $item1d = 'defines=[/D "_DEBUG"]'; my $item2d = 'outputs=[".\Debug"]'; my @arr = (); # add debug items @arr = (); # clear the array push(@arr,$item1d); push(@arr,$item2d); # store reference $aref = \@arr; $hash{$conf1} = [@{$aref}]; # add COPY of the array # add release items @arr = (); # clear the array push(@arr,$item1); push(@arr,$item2); $aref = \@arr; $hash{$conf2} = [@{$aref}]; # add COPY of the array foreach my $key (keys %hash) { #print $hash{$key}." "; # this would just print ARRAY(0xaddress) print "$key => "; my $ar2 = $hash{$key}; # extract the reference foreach my $itm (@{$ar2}) { # iterate the reference print "$itm "; } print "\n"; }
output:
proj|Release => defines=[/D "NDEBUG"] outputs=[".\Release"] proj|Debug => defines=[/D "_DEBUG"] outputs=[".\Debug"]
Also note the special notation to address the members of an array reference, like @{$ar2}...
In a more 'complex' situation, where a 'hash' is to be copied to,
and returned in another hash, inside an array - I wanted to return 'lots' of information in
one hash ... this example built from the good information contained in -
http://www.cs.mcgill.ca/~abatko/computers/programming/perl/howto/hash/
- a great page about hashes ...
code:
#!perl -w use strict; use warnings; my %hash = get_hash(); show_hash(\%hash); exit(0); sub show_hash { my ($hr) = @_; # get the hash reference my ($key, $val, $cnt, $i, $src, $h2r, $msg, $k, $v); prt( "Show hash (reference) contents ...\n" ); foreach $key (keys %{$hr}) { $val = $$hr{$key}; if ($key eq 'C_SOURCES') { $cnt = scalar @{$val}; # this is an array prt( "Got $cnt sources ...\n" ); for ($i = 0; $i < $cnt; $i++) { $src = $$val[$i][0]; $h2r = $$val[$i][3]; # this is a hash reference $msg = "$src "; foreach $k (keys %{$h2r}) { $v = $$h2r{$k}; $msg .= " [$k = $v]"; } prt( "$msg\n" ); } } else { prt( "$key = $val\n" ); } } } sub get_hash { my %h = (); my @srcs = (); my $hr; $h{'-NEW_RT_DBG'} = '/MDd'; $h{'-NEW_RT_REL'} = '/MD'; $hr = {}; # clear the hash reference $hr->{'debug'} = 'Debug'; # add some values $hr->{'release'} = 'Release'; push(@srcs, ["file1.c", "group", "filter", $hr]); # store it $hr = {}; # clear reference $hr->{'debug2'} = 'Debug/Dupe'; # add some other values $hr->{'release2'} = 'Release/Dupe'; push(@srcs, ["file2.c", "group", "filter", $hr]); # store it $h{'C_SOURCES'} = [@srcs]; # copy the array into the hash return %h; } sub prt { my ($txt) = shift; print $txt; } # eof
output:
Show hash (reference) contents ... -NEW_RT_DBG = /MDd Got 2 sources ... file1.c [debug = Debug] [release = Release] file2.c [debug2 = Debug/Dupe] [release2 = Release/Dupe] -NEW_RT_REL = /MD
Note such things as the clearing of the hash reference $hr = {};, the setting of values into the hash reference $hr->{'debug'} = 'Debug', the copying of the hash reference into the array push(@srcs, ['file1.c',...,$hr]);, copying of the array into the hash $h{'C_SOURCES'} = [@srcs];, and how to extract, and enumerate the members of the hash reference ...
You can create a reference to an anonymous array or hash by using square brackets for an array and braces for a hash:
code:
my $array_ref = ['apple', 'banana', 'orange']; my $hash_ref = {name => 'Becky', age => 23};
You can store an anonymous function in a hash, and call that function by:.
code:
#!perl -w use strict; use warnings; my %hash = (frogs => sub {print "Hello, World...\n"}); &{ $hash{frogs} }();
output:
Hello, World...
Use $master{$key} = { %hash } to COPY a hash:
code:
#!/bin/perl # NAME: copyhoh.pl # AIM: copy a hash, into a hash reference, as the value use strict; use warnings; my %collection = (); sub prt($) { print shift; } sub gen_hash($) { my ($hr) = shift; my %items = (); my ($i, $j, $i2, $j2, $key2, $val2, $key1); for ($j = 0; $j < 3; $j++) { $j2 = $j + 1; %items = (); # clear the hash $key1 = "KEY$j2"; for ($i = 0; $i < 3; $i++) { $i2 = $i + 1; $key2 = "key".($j2 * $i2); $val2 = "value".($j2 * $i2); $items{$key2} = $val2; # generate an item } $$hr{$key1} = { %items }; # COPY the HASH, into a HASH REF, as the value } } sub show_collection($) { my ($hr) = shift; my $max = scalar keys %$hr; prt( "Got $max keys...\n" ); foreach my $key1 (sort keys %$hr) { my $val1 = $$hr{$key1}; foreach my $key2 (sort keys %$val1) { my $val2 = $$val1{$key2}; prt( "$key1: $key2 = $val2\n" ); } } } gen_hash( \%collection ); show_collection( \%collection ); exit 0; # eof - copyhoh.pl
output:
Got 3 keys... KEY1: key1 = value1 KEY1: key2 = value2 KEY1: key3 = value3 KEY2: key2 = value2 KEY2: key4 = value4 KEY2: key6 = value6 KEY3: key3 = value3 KEY3: key6 = value6 KEY3: key9 = value9
A reference hash can be modified, including adding the contents of an 'anonymous' hash...
code:
#!/usr/bin/perl -w use strict; use warnings; use Data::Dumper; my %hash = ( 'key1' => 'val1', 'key2' => 'val2' ); sub get_hash_of_hash { my ($rh) = @_; my $tot = 0; foreach my $key (keys %{$rh}) { my $val = ${$rh}{$key}; # get current value $tot++; my %h = (); # build up an anonymous hash for (my $i = 0; $i < 2; $i++) { my $k2 = "KEY$i$tot"; my $v2 = "VAL$i$tot"; $h{$k2} = $v2; # store this } ${$rh}{$key} = [$val, \%h]; # and then 'ADD' this 'anonymous' hash, # together with the original value into an array reference } return $rh; } my $refh = \%hash; # conver to REFERENCE print "Dump of original...\n"; print Dumper($refh); # show original value my $rnh = get_hash_of_hash( $refh ); # modify, adding a generated hash print "Dump of modified...\n"; print Dumper($rnh); # show the results # eof
output:
Dump of original... $VAR1 = { 'key2' => 'val2', 'key1' => 'val1' }; Dump of modified... $VAR1 = { 'key2' => [ 'val2', { 'KEY01' => 'VAL01', 'KEY11' => 'VAL11' } ], 'key1' => [ 'val1', { 'KEY12' => 'VAL12', 'KEY02' => 'VAL02' } ] };
So the old value, be it a string, or and array ref, or what ever, and new hash (ref) are stored in an array reference in the original hash, replacing the old value... simple ;=))
A hash entry can be delete, using 'delete'
code:
my %hash = ( 'a' => 1, 'b' => 2, 'c' => 3 ); my @arr = qw( a b c ); foreach my $key (@arr) { if (defined $hash{$key}) { delete $hash{$key}; } } if (scalar keys(%hash) == 0) { prt("All deleted... ok\n"); } else { prt("Deletion FAILED\n"); }
output:
All deleted... ok
This is just some reference pages seen...
http://www.cs.mcgill.ca/~abatko/computers/programming/perl/howto/hash/
And that's it for now...
EOF - perl_hash.htm