270 likes | 310 Views
Understand the concept of hashes in Perl, learn available operations, and explore practical applications. Create, access, modify hash elements efficiently. Utilize 2-dimensional arrays and list representation techniques. Retrieve keys and values, and print hashes effectively.
E N D
Perl Hashes Learning Objectives: To understand the concept of Hash as a data structure To learn the operations of Hash which are available in Perl To understand the usage & application of hash in Perl
Array of Arrays • We can form 2-dimensional array as follows: @r1 = (1,2,3); @r2 = (4,5,6); @r3 = (7,8,9); # the backslash is to get the reference of a variable # so @m contains 3 pointers to 3 1-D arrays. @m = (\@r1,\@r2,\@r3); print $m[0][1], $m[1][0]; # prints 2,4 • Another way is to use the square bracket: @m = ([1,2,3], [4,5,6], [7,8,9]);
What is a Hash? • A hash (or associative array) is like an array, where the index can be any scalar value (not just small non-negative integers). • A hash index is called a key (keys must be unique). • The elements of a hash have no fixed order, unlike arrays. • The elements of a hash are like filing cards, where the top half of the card has the key, and the bottom half has the value. • The keys are used to lookup the values. “bill” “cheap” 16 2046.1 “0 C” “32 F” keys: values:
Hash Variables (1) • Hash variable names begin with the percent sign (%) followed by the usual variable name. • There is no relationship between $bill, @bill, and %bill, Perl considers them to be separate variables. • Each element of a hash is a separate scalar variable, accessed by the key. • Elements of the hash %bill, are referenced with $bill{$key}, where $key is any scalar expression.
Hash Variables (2) • As with arrays, you create new hash elements: $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; • Once created, you can access hash values similar to indexing arrays: print "Bill Gates is ", $bill{"Gates"}, "\n"; $n = "Clinton"; print "Bill $n is $bill{$n}\n"; $n = 234.5; print "Bill $n is $bill{$n}\n"; • Output: Bill Gates is cheap Bill Clinton is busy Bill 234.5 is 456.7
Hash Variables (3) • Once created, you can change hash values if needed: $bill{234.5} = 456.7; ... $bill{234.5} += 3; # makes it 459.7 • Referencing a hash element that does not exist returns the undef value.
List Representation of a Hash • You can access the hash as a whole if you need to initialize it or to copy it. • The hash unwinds as a list. Each pair in the list represents the key and its value. $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; @billarray = %bill; # @billarray: qw(Gates cheap Clinton busy 234.5 456.7) %a = @billarray; # create %a like %bill %a = %bill; # faster way to do the same %b = qw(Gates cheap Clinton busy 234.5 456.7); # initialize %b like %bill from list values • The order of the key-value pairs is random in the list representation and cannot be controlled. (Don’t rely on the ordering.)
Hash “reverse” • You can construct a hash with keys and values swapped using the reverse function: %aback = reverse %a; • If %a has two identical values, those will end up as a single element in %aback (reverse is best used on hashes with unique keys and values). $ cat reverse1 #!/usr/local/bin/perl5 -w $b{"Gates"} = "Bill"; $b{"Clinton"} = "Bill"; %revb = reverse %b; # print out revb key and value ... $ reverse1 Bill Gates $
Retrieving “keys” in a Hash (1) • The keys(%hashname) function returns a list of all the keys currently in the hash. $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; @list = keys(%bill); # @list gets qw(Gates Clinton 234.5) in some random order • If there are no elements in the hash, then keys() returns an empty list. • As with other Perl functions, the parentheses are optional: @list = keys %bill;
Retrieving “keys” in a Hash (2) • The keys function is often used in foreach loops to print or access the elements one-by-one: $ cat key #!/usr/local/bin/perl5 -w $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; foreach $k (sort(keys(%bill))){ print "At $k we have $bill{$k}\n"; } $ key At 234.5 we have 456.7 At Clinton we have busy At Gates we have cheap $
Printing Hashes • You cannot print the entire hash like you can print arrays: $ cat prhash #!/usr/local/bin/perl5 -w $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; print "Bill hash: %bill\n"; $ prhash Bill hash: %bill $ • Most Perl programmers use a foreach loop to print hashes (as in the previous slide).
“keys” again • In a scalar context, keys returns the number of elements in the hash: $ cat key1 #!/usr/local/bin/perl5 -w $n = keys(%bill); if($n==0){ print "Bill is empty\n"; exit; } print "Bill has $n elements\n"; $ key1 Bill is empty $ • exit is like the C++ exit() function, and ends the program immediately.
Retrieving “values” in a hash • The values(%hashname) function returns a list of all the values currently in the hash. • The values are in exactly the same order as the keys returned by keys(%hashname). $ cat value #!/usr/local/bin/perl5 -w $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; @klist = keys(%bill); @vlist = values(%bill); print "@klist\n"; print "@vlist\n"; $ value 234.5 Gates Clinton 456.7 cheap busy $
each • Another way to print a hash is with the each function. • each returns a key-value pair as a two-element list. • Each time each is called it returns the next key-value pair until all the elements have been accessed. • When no more pairs, each returns an empty list. $ cat each #!/usr/local/bin/perl5 -w $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; while(($k,$v) = each(%bill)){ print "At $k we have $v\n"; } $ each At 234.5 we have 456.7 At Gates we have cheap At Clinton we have busy $
“delete” a Hash element with a key • How to remove hash elements? Answer: Use the delete function. • The argument is the keyed reference to be deleted: $ cat delete1 #!/usr/local/bin/perl5 -w $bill{"Gates"} = "cheap"; $bill{"Clinton"} = "busy"; $bill{234.5} = 456.7; delete $bill{"Gates"}; while(($k,$v) = each(%bill)){ print "At $k we have $v\n"; } $ delete1 At 234.5 we have 456.7 At Clinton we have busy $
Hash Slices (1) • Like an array, a hash can be sliced to access a collection of elements. • We can use a hash slice to compact initialization. For example: $b{"Gates"} = "cheap"; $b{"Clinton"} = "busy"; $b{234} = 45; can be shortened to: ($b{"Gates"},$b{"Clinton"},$b{234}) = qw(cheap busy 45); can be hash sliced as: @b{"Gates","Clinton",234} = qw(cheap busy 45); (Note that it is @b, not %b.) • Another example: @b{"A" .. "Z"} = (1 .. 26);
Hash Slices (2) • We can also use a hash slice with variable interpolation : $ cat hslice #!/usr/local/bin/perl5 -w @b{"Gates","Clinton",234} = qw(cheap busy 45); @k = qw(Gates Clinton); print "The values are: @b{@k}\n"; $ hslice The values are: cheap busy $
Hash Slices - Merging Hashes (1) • Hash slices can also be used to merge hashes. • In the following example, if there are duplicate keys, the values overwritten by the %small hash: $ cat merge #!/usr/local/bin/perl5 -w @big{"Gates","Clinton",234} = qw(cheap busy 45); @small{"Horner",234} = qw(111 67); @big{keys %small} = values %small; while(($k,$v) = each(%big)){ print "At $k we have $v\n"; } $ merge At 234 we have 67 At Gates we have cheap At Horner we have 111 At Clinton we have busy $
Hash Slices - Merging Hashes (2) • A simpler (though slower) way to merge hashes is: $ cat merge1 #!/usr/local/bin/perl5 -w @big{"Gates","Clinton",234} = qw(cheap busy 45); @small{"Horner",234} = qw(111 67); %big = (%big, %small); while(($k,$v) = each(%big)){ print "At $k we have $v\n"; } $ merge1 At 234 we have 67 At Gates we have cheap At Horner we have 111 At Clinton we have busy $
Command line & Environment (1) • The name of your Perl script is $0 • The array for command line parameter is @ARGV • The process ID of your Perl script is $$ • Last shell execution status: $? (backtick ` ` command, or system operator) • The hash containing your current environment: %ENV
Command line & Environment (2) $ cat p1 #!/usr/local/bin/perl5 -w $argc = @ARGV; print "parameter count $argc for $0 (PID: $$)\n"; print "parmamters: $ARGV[0] $ARGV[1]\n"; # put both input and error to /dev/null which means # # don’t print anything. 2>&1 is a unix command for # grouping both standard output and error together, and # put the result into standard output. system "cat non_existing_file > /dev/null 2>&1"; print "Status of last command: $? \n"; system "cd"; print "Status of last command: $? \n"; print "You are $ENV{USER} \n"; $ p1 a b parameter count 2 for p1 (PID: 20489) parmamters: a b Status of last command: 512 Status of last command: 0 You are kwchiu
More About Hashes • Another way to initialize hashes: $ cat morehash #!/usr/local/bin/perl5 -w %bill = ( "Gates" => "cheap", "Clinton" => "busy"); print "Hello $bill{'Gates'} Bill!\n"; $ morehash Hello cheap Bill! • You may use single quotes for specifying a key (more convenient inside double quotes).
Use of Hash • Simple hash as simple relations: $Name{94001} = "Peter"; $Name{94002} = "John"; • Simple hash as records: $John{"studno"} = 94002; $John{"CGA"} = 9.1; $John{"SGA"} = 8.7; ... • Hash of hashes: (database) tables
Note { } for creating an anonymous hash instead of (); $student{94002} now contains a pointer to that hash Hash of Hashes (2) • Idea: hash element is a hash pointer $ cat hashofhash $student{94001}{'name'} = "John"; $student{94001}{'CGA'} = 9.1; print $student{94001}{'name'}; $student{94002} = {"name" => "Peter", "CGA" => 8.5}; foreach $s (keys(%student)) { print "Student $s: "; print "Name = $student{$s}{'name'}; "; print "CGA = $student{$s}{'CGA'}\n"; } $ hashofhash John Student 94001: Name = John; CGA = 9.1 Student 94002: Name = Peter; CGA = 8.5
Hash of Hashes of Hashes • We can form complicated nested data structures with repeated levels of hashes: $ cat hash3 #!/usr/local/bin/perl5 -w$ $student{94001}{'grade'}= {"comp111"=>'A',"comp211"=>'B+'}; print $student{94001}{'grade'}{'comp111'}; $p = $student{94001}{'grade'}; # $p is a ptr foreach $c (keys(%$p)) { # %$p - the hash pointed by p print "$c $$p{$c}\n"; } # $$p{...} - an element of the hash pointed by p $ hash3 comp111 A comp211 B+