perl hashes learning objectives: 1. to understand the concept of hash as a data structure 2. to...

26
Perl Hashes Learning Objectives: 1. To understand the concept of Hash as a data structure 2. To learn the operations of Hash which are available in Perl 3. To understand the usage & application of hash in Perl

Post on 20-Dec-2015

216 views

Category:

Documents


2 download

TRANSCRIPT

Perl Hashes

Learning Objectives:1. To understand the concept of Hash as a data

structure

2. To learn the operations of Hash which are available in Perl

3. To understand the usage & application of hash in Perl

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 22

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]);

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 33

“bill”

“cheap”

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.

16

2046.1

“0 C”

“32 F”

keys:

values:

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 44

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.

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 55

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 busyBill 234.5 is 456.7

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 66

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.

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 77

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.)

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 88

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... $ reverse1Bill Gates$

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 99

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;

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1010

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";}$ keyAt 234.5 we have 456.7At Clinton we have busyAt Gates we have cheap$

Retrieving “keys” in a Hash (2)

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1111

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";$ prhashBill hash: %bill$

Most Perl programmers use a foreach loop to print hashes (as in the previous slide).

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1212

“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";$ key1Bill is empty$

exit is like the C++ exit() function, and ends the program immediately.

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1313

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"; $ value234.5 Gates Clinton456.7 cheap busy$

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1414

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";}$ eachAt 234.5 we have 456.7At Gates we have cheapAt Clinton we have busy$

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1515

“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";}$ delete1At 234.5 we have 456.7At Clinton we have busy$

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1616

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);

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1717

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";$ hsliceThe values are: cheap busy$

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1818

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";}$ mergeAt 234 we have 67At Gates we have cheapAt Horner we have 111At Clinton we have busy$

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 1919

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";}$ merge1At 234 we have 67At Gates we have cheapAt Horner we have 111At Clinton we have busy$

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 2020

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

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 2121

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 bparameter count 2 for p1 (PID: 20489)parmamters: a bStatus of last command: 512Status of last command: 0You are kwchiu

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 2222

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";$ morehashHello cheap Bill!

You may use single quotes for specifying a key (more convenient inside double quotes).

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 2323

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

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 2424

Hash of Hashes (1)

Student#

(key)

Attributes

Name CGA Grades

94001 John 9.1 comp111 => A

comp211 => B+

94002 Peter 8.5 …

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 2525

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

Note { } for creating an anonymous hash instead of ();

$student{94002} now contains a pointer to that hash

Note { } for creating an anonymous hash instead of ();

$student{94002} now contains a pointer to that hash

COMP111COMP111Lecture 13 / Slide Lecture 13 / Slide 2626

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 ptrforeach $c (keys(%$p)) { # %$p - the hash pointed by p print "$c $$p{$c}\n";} # $$p{...} - an element of the hash pointed by p

$ hash3comp111 Acomp211 B+