Grzegorz Ro┼╝niecki
and 1 contributors

NAME

Tie::LLHash - Ordered hashes

DESCRIPTION

This class implements an ordered hash-like object. It's a cross between a Perl hash and a linked list. Use it whenever you want the speed and structure of a Perl hash, but the orderedness of a list.

See also Tie::IxHash by Gurusamy Sarathy. It's similar (it also does tied ordered hashes), but it has a different internal data structure and a different flavor of usage. Tie::IxHash stores its data internally as both a hash and an array in parallel. Tie::LLHash stores its data as a bidirectional linked list, making both inserts and deletes very fast. Tie::IxHash therefore makes your hash behave more like a list than Tie::LLHash does. This module keeps more of the hash flavor.

SYNOPSIS

 use Tie::LLHash;

 # A new empty ordered hash:
 tie (%hash, "Tie::LLHash");
 # A new ordered hash with stuff in it:
 tie (%hash2, "Tie::LLHash", key1=>$val1, key2=>$val2);
 # Allow easy insertions at the end of the hash:
 tie (%hash2, "Tie::LLHash", {lazy=>1}, key1=>$val1, key2=>$val2);

 # Add some entries:
 (tied %hash)->first('the' => 'hash');
 (tied %hash)->insert('here' => 'now', 'the');
 (tied %hash)->first('All' => 'the');
 (tied %hash)->insert('are' => 'right', 'the');
 (tied %hash)->insert('things' => 'in', 'All');
 (tied %hash)->last('by' => 'gum');

 $value = $hash{'things'}; # Look up a value
 $hash{'here'} = 'NOW';    # Set the value of an existing record
                           # or insert as last node in lazy mode

 $key = (tied %hash)->key_before('in');  # Returns the previous key
 $key = (tied %hash)->key_after('in');   # Returns the next key

 # Luxury routines:
 $key = (tied %hash)->current_key;
 $val = (tied %hash)->current_value;
 (tied %hash)->next;
 (tied %hash)->prev;
 (tied %hash)->reset;

 # If lazy mode is set, new keys will be added at the end.
 $hash{newkey} = 'newval';
 $hash{newkey2} = 'newval2';

METHODS

  • insert(key, value, previous_key)

    This inserts a new key-value pair into the hash right after the previous_key key. If previous_key is undefined (or not supplied), this is exactly equivalent to first(key, value). If previous_key is defined, then it must be a string which is already a key in the hash - otherwise we'll croak().

  • first(key, value) (or) first()

    Gets or sets the first key in the hash. Without arguments, simply returns a string which is the first key in the database. With arguments, it inserts a new key-value pair at the beginning of the hash.

  • last(key, value) (or) last()

    Gets or sets the last key in the hash. Without arguments, simply returns a string which is the last key in the database. With arguments, it inserts a new key-value pair at the end of the hash.

  • key_before(key)

    Returns the name of the key immediately before the given key. If no keys are before the given key, returns undef.

  • key_after(key)

    Returns the name of the key immediately after the given key. If no keys are after the given key, returns undef.

  • current_key()

    When iterating through the hash, this returns the key at the current position in the hash.

  • current_value()

    When iterating through the hash, this returns the value at the current position in the hash.

  • next()

    Increments the current position in the hash forward one item. Returns the new current key, or undef if there are no more entries.

  • prev()

    Increments the current position in the hash backward one item. Returns the new current key, or undef if there are no more entries.

  • reset()

    Resets the current position to be the start of the order. Returns the new current key, or undef if there are no keys.

ITERATION TECHNIQUES

Here is a smattering of ways you can iterate over the hash. I include it here simply because iteration is probably important to people who need ordered data.

 while (($key, $val) = each %hash) {
    print ("$key: $val\n");
 }

 foreach $key (keys %hash) {
    print ("$key: $hash{$key}\n");
 }

 my $obj = tied %hash;  # For the following examples

 $key = $obj->reset;
 while (exists $hash{$key}) {
    print ("$key: $hash{$key}\n");
    $key = $obj->next;
 }

 $obj->reset;
 while (exists $hash{$obj->current_key}) {
    $key = $obj->current_key;
    print ("$key: $hash{$key}\n");
    $obj->next;
 }

WARNINGS

  • Unless you're using lazy mode, don't add new elements to the hash by simple assignment, a la $hash{$new_key} = $value, because Tie::LLHash won't know where in the order to put the new element and will die.

  • Evaluating tied hash in scalar context wasn't implemented until Perl 5.8.3, so on earlier Perl versions it will always return 0, even if hash is not empty.

TODO

  • Add support for NEXTKEY and next with additional argument.

  • I could speed up the keys() routine in a scalar context if I knew how to sense when NEXTKEY is being called on behalf of keys(). Not sure whether this is possible.

SEE ALSO

COPYRIGHT AND LICENSE

Ken Williams <kenahoo@gmail.com>

Copyright (c) 1998 Swarthmore College. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.