| Tie::AliasHash(3pm) | User Contributed Perl Documentation | Tie::AliasHash(3pm) |
Tie::AliasHash - Hash with aliases key (multiple keys, one value)
use Tie::AliasHash;
tie %hash, 'Tie::AliasHash';
$hash{ 'foo', 'bar' } = 'baz';
print $hash{foo}; # prints 'baz'
print $hash{bar}; # prints 'baz' too
$hash{bar} = 'zab'; # $hash{foo} is changed too
print $hash{foo}; # prints 'zab'
Tie::AliasHash creates hashes that can have multiple keys for a single value. This means that some keys are just 'aliases' for other keys.
The example shown in the synopsys above creates a key 'foo' and an alias key 'bar'. The two keys share the same value, so that fetching either of them will always return the same value, and storing a value in one of them will change both.
The only difference between the two keys is that 'bar' is not reported by keys() and each():
use Tie::AliasHash;
tie %hash, 'Tie::AliasHash';
tied(%hash)->add_alias( 'foo', 'bar' );
foreach $k (keys %hash) { print "$k\n"; } # prints 'foo'
To get the 'real' keys and the aliases together, use the "allkeys" function:
use Tie::AliasHash;
tie %hash, 'Tie::AliasHash';
tied(%hash)->add_alias( 'foo', 'bar' );
foreach $k (tied(%hash)->allkeys) { print "$k\n"; } # prints 'foo' and 'bar'
You can create alias keys with 3 methods:
The 'tie' constructor accepts an optional list of key names and aliases. The synopsis is:
tie %HASH, 'Tie::AliasHash',
KEY => ALIAS,
KEY => [ALIAS, ALIAS, ALIAS, ...],
...
tied(%hash)->add_alias( KEY, ALIAS );
tied(%hash)->add_alias( KEY, ALIAS, ALIAS, ALIAS, ... );
$hash{ KEY, ALIAS } = VALUE;
$hash{ KEY, ALIAS, ALIAS, ALIAS, ... } = VALUE;
The list of keys and aliases can be either an array reference, eg.:
$hash{ [ 'foo', 'bar', 'baz' ] } = $value;
$hash{ \@foobarbaz } = $value;
or an explicit list, eg.:
$hash{ qw(foo bar baz) } = $value;
$hash{ @foobarbaz } = $value;
Be warned that, with the last example, Perl uses the $; variable (or subscript separator), which defaults to '\034' (ASCII 28). This can cause problems if you plan to use keys with arbitrary ASCII characters. Always use the first form when in doubt. Consult perlvar for more information.
None by default. You can optionally export the "allkeys" function to your main namespace, so that it can be used like the builtin "keys".
use Tie::AliasHash 'allkeys';
tie %hash, 'Tie::AliasHash';
foreach $k (allkeys %hash) { print "$k\n"; }
But see CAVEATS below for important information about "allkeys".
This module can generate a wonderful amount of confusion if not used properly. The package should really have a big 'HANDLE WITH CARE' sticker on it. Other than paying special attention to what you're doing, you should be aware of the following subtlenesses:
Aliases are 'transitive', and always resolve to their aliased key. This means that if you write:
use Tie::AliasHash;
tie %hash, 'Tie::AliasHash';
tied(%hash)->add_alias( 'foo', 'bar' );
tied(%hash)->add_alias( 'bar', 'baz' );
$hash{baz} is created as an alias for $hash{foo}, not for $hash{bar} (which isn't a real key). This also means that if you later change $hash{bar} to point to something else, you haven't changed $hash{baz}:
tied(%hash)->add_alias( 'gup', 'bar' );
# $hash{bar} is now really --> $hash{gup}
# $hash{baz} is still --> $hash{foo}
The builtin "delete" function resolves aliases to real keys, so it deletes everything even when called on an alias:
use Tie::AliasHash;
tie %hash, 'Tie::AliasHash';
tied(%hash)->add_alias( 'foo', 'bar' );
delete $hash{bar}; # deletes $hash{foo} too!
To delete an alias leaving its key intact, use the "remove_alias" method instead:
use Tie::AliasHash;
tie %hash, 'Tie::AliasHash';
tied(%hash)->add_alias( 'foo', 'bar' );
tied(%hash)->remove_alias( 'bar' ); # $hash{foo} remains intact
The builtin "exists" function returns true on aliases too:
use Tie::AliasHash;
tie %hash, 'Tie::AliasHash';
tied(%hash)->add_alias( 'foo', 'bar' );
print exists $hash{'foo'}; # TRUE
print exists $hash{'bar'}; # TRUE
To distinguish between aliases and real keys, use the "is_key" method:
print exists $hash{'foo'} and tied(%hash)->is_key('foo'); # TRUE
print exists $hash{'bar'} and tied(%hash)->is_key('bar'); # FALSE
If you export "allkeys" into your main namespace, it can be used as the builtin "keys" in the following code:
use Tie::AliasHash 'allkeys';
tie %hash, 'Tie::AliasHash';
foreach $key (allkeys %hash) { print "$key\n"; }
But note that "allkeys" is always a function call, so this does not work as you expect:
foreach $key (sort allkeys %hash) { print "$key\n"; }
You have to fool "sort", or it will use "allkeys" as its sort routine. This can be done by providing an explicit sort routine, or forcing the result of "allkeys" to be interpreted as an array by referencing-dereferencing it, or with a two-step operation where you first assign "allkeys" to an array, and then operate on it:
foreach $key (sort { $a cmp $b } allkeys %hash) { print "$key\n"; }
foreach $key (sort @{[ allkeys %hash ]}) { print "$key\n"; }
@allkeys = allkeys %hash;
foreach $key (sort @allkeys) { print "$key\n"; }
The most potentially confusing feature of this module is the 'jolly' key. When you set a value for it, all 'unknown' keys become aliases for the jolly key. This means that you can't create new keys in the hash, because if a key does not exists, the value will be 'redirected' to the jolly key.
We make an example of how this works and for what can be useful. Suppose you have a table of records with a 'city' field. You want to count the occurrencies for Rome, Paris and London (possibly expressed in different languages), and count every other city as 'Other'.
tie %cities, 'Tie::AliasHash';
$cities{['Rome', 'Roma', 'Rom']} = 0;
$cities{['Paris', 'Parigi']} = 0;
$cities{['London', 'Londra', 'Londres']} = 0;
$cities{'Other'} = 0;
tied(%cities)->set_jolly('Other');
while($city = get_city()) {
$cities{$city}++;
}
foreach $city (sort keys %cities) {
print "$city:\t$cities{$city}\n";
}
A possible output for the above script can be:
London: 4
Other: 92
Paris: 7
Rome: 16
Also note that the use of the jolly key is limited to fetch and store, it does not affect other hash operations, like exists, delete, each, keys and values.
-CAXn Tie::AliasHash
Aldo Calpini <dada@perl.it>
| 2024-10-13 | perl v5.38.2 |