## Hashes

This lecture notes is based on Prof Doreen De Leon's lectures.

Learning Perl, Chapter 5 Hashes.

### Definition

• A hash is a collection of scalar data, similar to an array, whose elements are accessed by an index value.
• Unlike an array, the index values are arbitrary, unique strings, called keys.
• The elements in a hash are arranged in no particular order. Perl stores the key-value pairs in an internal order to make it easier to find a specific value.

### Hash Variables

• A hash variable name is preceded by a percent sign (%).
• A hash is commonly created and accessed by referring to its elements.
• Each element is a separate scalar variable accessed by a string index (the key).
• Example: If %hash is a hash variable, we can access element by \$hash{\$key}.
```\$table{100} = 256; # "100" is key, 256 is value
\$table{"abc"} = "def"; # "abc" is key, "def" is value
\$table{100}+=3; #259
print \$table{"abc"}, "\n"; # def
print \$table{100}, "\n"; #259
```
```for(\$i = 1; \$i < 10; \$i++) {
\$square_table{\$i} = \$i * \$i;
}

print \$square_table{5}; #25
```
```\$capital{"USA"} = "Washington D.C.";
\$capital{"France"} = "Paris";
\$capital{"China"} = "Beijing";
\$capital{"Japan"} = "Tokyo";

print \$capital{"USA"}, "\n"; # Washington D.C.
```

### Alternate Initialization

• Assign a list to a hash: each pair of values indicates one key/value association.
```\$capital{"France"} = "Paris";
\$capital{"China"} = "Beijing";
\$capital{"Japan"} = "Tokyo";
@array = %capital;
# array becomes
# France Paris China Beijing Japan Tokyo

print "@array";
```
```%capital = qw(France Paris China Beijing Japan Tokyo);

print \$capital{"France"},"\n" ; # Paris
print \$capital{"China"}, "\n"; # Beijing
```
```@array = ("111222333","Charles", "222333555", "Mary");
%student = @array;

print \$student{"111222333"}; #Charles
```

### The Big Arrow Operator (`=>`)

• The big arrow operator can be used in place of commas between key/value pairs.
• NOTE: Technically, quotes to the left of the big arrow can be omitted because any bareword (a sequence of characters consisting of only letters, digits, and underscores and not starting with a digit) to the left of the big arrow is automatically implicitly quoted by the big arrow.
```%capital = ("France" => "Paris", "China" => "Beijing", "Japan" => "Tokyo");
# actually you can remove the quotes
# %capital = (France => Paris, China => Beijing, Japan => Tokyo);
print \$capital{"France"}; #Paris
```

### General Notes

• There is NO literal representation of a hash.
• Can make a copy of a hash variable with the assignment operator (rarely done).
• Can construct a hash with keys and values swapped using the reverse operator. If the original hash has two identical values, only get a single element in the reversed hash (the last one on Perl's internal list with that value).
```%capital = ("France" => "Paris", "China" => "Beijing", "Japan" => "Tokyo");
%country = reverse %capital;

print \$country{"Paris"}; #France
```

### Hash Functions

1. keys    Syntax: keys %hash
2. values    Syntax: values %hash
3. each    Syntax: each %hash
4. delete   Syntax: delete \$hash{\$key};
5. exists   Syntax: exists \$hash{\$key};
```%capital = ("France" => "Paris", "China" => "Beijing", "Japan" => "Tokyo");
@countries = keys(%capital); # France, China, Japan

foreach \$country(@countries) {
print "The capital of \$country is \$capital{\$country}.\n";
}

# Output
# The capital of France is Paris.
# The capital of China is Beijing.
# The capital of Japan is Tokyo.
```
```%capital = ("France" => "Paris", "China" => "Beijing", "Japan" => "Tokyo");
@cities = values(%capital);
print "@cities"; #Paris Beijing Tokyo
```
```%capital = ("France" => "Paris", "China" => "Beijing", "Japan" => "Tokyo");

while ((\$country, \$city) = each(%capital)) {
print "The capital of \$country is \$city.\n";
}

# Output
# The capital of France is Paris.
# The capital of China is Beijing.
# The capital of Japan is Tokyo.
```
```%capital = ("France" => "Paris", "China" => "Beijing", "Japan" => "Tokyo");

if(exists(\$capital{"France"})) { # true
print "The key France exists.\n";
} else {
print "The key France doesn\'t exists.\n";
}

delete \$capital{"France"};

if(exists(\$capital{"France"})) { # false
print "The key France exists.\n";
} else {
print "The key France doesn\'t exists.\n";
}

```

### Hash Slices

• Access a collection of elements of a hash (as a list).
• A slice can be interpolated in a double-quoted string. So, can use a slice to print.
• A slice can be used to merge a smaller hash into a larger one. If there are duplicate keys, those of the smaller hash used.
```(\$scores{"Amy"}, \$scores{"Ben"}, \$scores{"Cathy"}) = (55, 66, 77);
print \$scores{"Ben"},"\n"; # 66

@scores{"Dave", "Eva", "Fred"} = (71, 81, 91);
print \$scores{"Eva"}, "\n"; # 81

@names = ("Gloria", "Heather", "Ivy");
@scores{@names} = (23, 34, 45);
print \$scores{"Ivy"}, "\n"; # 45;

@names2 = qw(Ben Fred Dave);
print "@scores{@names2}\n"; # 66 91 71

(\$scores2{"Jen"}, \$scores2{"Ken"}, \$scores{"Ivy"}) = (10,20,30);

%new = (%scores, %scores2); # join 2 score set
print \$new{"Gloria"},"\n"; # 23
print \$new{"Ivy"},"\n"; # 30
print \$new{"Ken"}, "\n"; # 20

# another way to join 2 hash
# faster than the previous method
@scores{keys %scores2} = values %scores2;
print \$scores{"Gloria"},"\n"; # 23
print \$scores{"Ivy"},"\n"; # 30
print \$scores{"Ken"},"\n"; # 20
```