NAME
Data::XHash - Extended, ordered hash (commonly known as an associative array or map) with key-path traversal and automatic index keys
VERSION
Version 0.01
SYNOPSIS
use Data::XHash;
use Data::XHash qw/xhash xhashref/;
use Data::XHash qw/xh xhn xhr xhrn/;
$tiedhref = Data::XHash->new(); # A blessed and tied hashref
# Note: Don't call "tie" yourself!
# Exports are shortcuts to call Data::XHash->new()->push()
# or Data::XHash->new()->pushref() for you.
$tiedhref = xh('auto-indexed', { key => 'value' });
$tiedhref = xhash('auto-indexed', { key => 'value' });
$tiedhref = xhashref([ 'auto-indexed', { key => 'value' } ]);
$tiedhref = xhn('hello', { root => { branch =>
[ { leaf => 'value' }, 'world' ] } }); # (nested)
$tiedhref = xhr([ 'auto-indexed', { key => 'value' } ]);
$tiedhref = xhrn([ 'hello', { root => { branch =>
[ { leaf => 'value' }, 'world' ] } } ]); # (nested)
# Note: $xhash means you can use either $tiedhref or the
# underlying object at tied(%$tiedhref)
## Hash-like operations
# Getting keys or paths
$value = $tiedhref->{$key};
$value = $tiedhref->{\@path};
$value = $xhash->fetch($key);
$value = $xhash->fetch(\@path);
# Auto-vivify a Data::XHash at the end of the path
$tiedhref2 = $tiedhref1->{ [ @path, {} ] };
$tiedhref->{ [ @path, {} ] }->$some_xh_method(...);
$tiedhref = $xhash->fetch( [ @path, {} ] );
$xhash->fetch( [ @path, {} ] )->$some_xh_method(...);
# Setting keys or paths
$tiedhref->{$key} = $value;
$tiedhref->{\@path} = $value;
$xhash->store($key, $value, %options);
$xhash->store(\@path, $value, %options);
# Setting the next auto-index key
$tiedhref->{[]} = $value; # Recommended syntax
$tiedhref->{+undef} = $value;
$tiedhref->{[ undef ]} = $value; # Any path key may be undef
$xhash->store([], $value, %options);
$xhash->store(undef, $value, %options);
$xhash->store([ undef ], $value, %options);
# Clear the xhash
%$tiedhref = ();
$xhash->clear();
# Delete a key and get its value
$value = delete $tiedhref->{$key}; # or \@path
$value = $xhash->delete($key); # or \@path
# Does a key exist?
$boolean = exists $tiedhref->{$key}; # or \@path
$boolean = $xhash->exists($key); # or \@path
# Keys and lists of keys
@keys = keys %$tiedhref; # All keys; resets iterator
@keys = $xhash->keys(%options);
$key = $xhash->first_key();
$key2 = $xhash->next_key($key1);
$key = $xhash->last_key();
$key = $xhash->next_index(); # The next auto-index key
# Values
@all_values = values %$tiedhref;
@some_values = @{%$tiedhref}{@keys}; # or pathrefs
@all_values = $xhash->values();
@some_values = $xhash->values(\@keys); # or pathrefs
($key, $value) = each(%$tiedhref); # Key/value iteration
# Does the hash contain any key/value pairs?
$boolean = scalar(%$tiedhref);
$boolean = $xhash->scalar();
## Array-like operations
$value = $xhash->pop(); # last value
($key, $value) = $xhash->pop(); # last key/value
$value = $xhash->shift(); # first value
($key, $value) = $xhash->shift(); # first key/value
# Append values or { keys => values }
$xhash->push(@elements);
$xhash->pushref(\@elements, %options);
# Insert values or { keys => values }
$xhash->unshift(@elements);
$xhash->unshiftref(\@elements, %options);
# Export in array-like fashion
@list = $xhash->as_array(%options);
$list = $xhash->as_arrayref(%options);
# Export in hash-like fasion
@list = $xhash->as_hash(%options);
$list = $xhash->as_hashref(%options);
# Reorder elements
$xhash->reorder($reference, @keys); # [] = sorted index_only
# Remap elements
$xhash->remap(%mapping); # or \%mapping
$xhash->renumber(%options);
## TIEHASH methods - see perltie
# TIEHASH, FETCH, STORE, CLEAR, FIRSTKEY, NEXTKEY
DESCRIPTION
Data::XHash provides an object-oriented interface to tied, ordered hashes. Hash elements may be assigned keys explicitly or automatically in mix-and-match fashion like arrays in PHP.
It also includes support for trees of nested XHashes, tree traversal, and conversion to and from native Perl data structures.
Suggested uses include structured configuration information or HTTP query parameters in which order may at least sometimes be significant, for passing mixed positional and named parameters, or for porting PHP code.
EXPORTS
You may export any of the shortcut functions. None are exported by default.
FUNCTIONS
$tiedref = xh(@elements)
$tiedref = xhash(@elements)
$tiedref = xhashref(\@elements, %options)
$tiedref = xhn(@elements)
$tiedref = xhr(\@elements, %options)
$tiedref = xhrn(\@elements, %options)
These convenience functions call Data::XHash->new()
and then pushref()
the specified elements. The "r" and "ref" versions take an arrayref of elements; the others take a list. The "n" versions are shortcuts for the nested => 1
option of pushref()
.
$tiedref = xh('hello', {root=>xh({leaf=>'value'}),
{list=>xh(1, 2, 3)});
$tiedref = xhn('hello', {root=>{leaf=>'value'}},
{list=>[1, 2, 3]});
METHODS
Data::XHash->new( )
$xhash->new( )
This creates a new Data::XHash object and ties it to a new, empty hash. It blesses the hash as well and returns a reference to the hash ($tiedref
).
Do not use tie %some_hash, 'Data::XHash';
- it will croak!
$tiedref->{$key}
$tiedref->{\@path}
$xhash->fetch($key)
$xhash->fetch(\@path)
Returns the value for the specified hash key, or undef
if the key does not exist.
If the key parameter is reference to a non-empty array, its elements are traversed as a path through nested XHashes.
If the last path element is a hashref, the path will be auto-vivified (Perl-speak for "created when referenced") and made to be an XHash if necessary (think "fetch a path to a hash"). Otherwise, any missing element along the path will cause undef
to be returned.
$xhash->{[]}; # undef
$xhash->{[qw/some path/, {}]}->isa('Data::XHash'); # always true
# Similar to native Perl: $hash->{some}{path} ||= {};
$tiedref->{$key} = $value
$tiedref->{\@path} = $value
$xhash->store($key, $value, %options)
$xhash->store(\@path, $value, %options)
Stores the value for the specified key in the XHash. Any existing value for the key is overwritten. New keys are stored at the end of the XHash.
If the key parameter is a reference to a non-empty array, its elements are traversed as a path through nested XHashes. Path elements will be auto-vivified as necessary and intermediate ones will be forced to XHashes.
If the key is an empty path or the undef
value, or any path key is the undef
value, the next available non-negative integer index in the corresponding XHash is used instead.
Returns the XHash tiedref or object (whichever was used).
Options:
- nested => $boolean
-
If this option is true, arrayref and hashref values will be converted into XHashes.
%$tiedref = ()
$xhash->clear( )
Clears the XHash.
Returns the XHash tiedref or object (whichever was used).
delete $tiedref->{$key} # or \@path
$xhash->delete($key) # or \@path
$xhash->delete(\%options?, @keys)
Removes the element with the specified key and returns its value. It quietly returns undef
if the key does not exist.
The method call can also delete (and return) multiple local (not path) keys at once.
Options:
- to => $destination
-
If
$destination
is an arrayref, hashref, or XHash, each deleted{ $key =
$value }> is added to it and the destination is returned instead of the most recently deleted value.
exists $tiedref->{$key} # or \@path
$xhash->exists($key) # or \@path
Returns true if the key (or path) exists.
$xhash->first_key( )
Returns the first key (or undef
if the XHash is empty).
$xhash->next_key($key)
Returns the key after $key
, or undef
if $key
is the last key or doesn't exist.
Path keys are not supported.
$xhash->last_key( )
Returns the last key, or undef
if the XHash is empty.
$xhash->next_index( )
Returns the next numeric insertion index. This is either "0" or one more than the current largest non-negative integer index.
scalar(%$tiedref)
$xhash->scalar( )
Returns true if the XHash is not empty.
$xhash->keys(%options)
This method is equivalent to keys(%$tiedref)
but may be called on the object.
Options:
- index_only => $boolean
-
If true, only the integer index keys are returned. If false, all keys are returned,
- sorted => $boolean
-
If index_only mode is true, this option determines whether index keys are returned in ascending order (true) or XHash insertion order (false).
$xhash->values([keys]?)
This method is equivalent to values(%$tiedref)
but may be called on the object.
You may optionally pass a reference to an array of keys whose values should be returned (equivalent to the slice @{$tiedref}{@$keys}
).
$xhash->pop( )
$xhash->shift( )
Removes the first element (shift) or last element (pop) from the XHash and returns its value (in scalar context) or its key and value (in list context). If the XHash was already empty, undef
or ()
is returned instead.
$xhash->push(@elements)
$xhash->pushref(\@elements, %options)
$xhash->unshift(@elements)
$xhash->unshiftref(\@elements, %options)
Appends elements at the end of the XHash (push()
and pushref()
) or inserts elements at the beginning of the XHash (unshift()
and unshiftref()
).
Scalar elements are automatically assigned a numeric index using next_index()
. Hashrefs are added as key/value pairs. References to references are dereferenced by one level before being added. (To add a hashref as a hashref rather than key/value pairs, push or unshift a reference to the hashref instead.)
Returns the XHash tiedref or object (whichever was used).
Options:
- at_key => $key
-
This will push after
$key
instead of at the end of the XHash or unshift before$key
instead of at the beginning of the XHash. This only applies to the first level of a nested push or unshift.This must be a local key (not a path), and the operation will croak if the key is not found.
- nested => $boolean
-
If true, values that are arrayrefs (possibly containing hashrefs) or hashrefs will be recursively converted to XHashes.
$xhash->as_array(%options)
$xhash->as_arrayref(%options)
$xhash->as_hash(%options)
$xhash->as_hashref(%options)
These methods export the contents of the XHash as native Perl arrays or arrayrefs.
The "array" versions return the elements in an "array-like" array or array reference; elements with numerically indexed keys are returned without their keys.
The "hash" versions return the elements in an "hash-like" array or array reference; all elements, including numerically indexed ones, are returned with keys.
xh( { foo => 'bar' }, 123, \{ key => 'value' } )->as_arrayref();
# [ { foo => 'bar' }, 123, \{ key => 'value'} ]
xh( { foo => 'bar' }, 123, \{ key => 'value' } )->as_hash();
# ( { foo => 'bar' }, { 0 => 123 }, { 1 => { key => 'value' } } )
xh(xh({ 3 => 'three' }, { 2 => 'two' })->as_array())->as_hash();
# ( { 0 => 'three' }, { 1 => 'two' } )
xh( 'old', { key => 'old' } )->push(
xh( 'new', { key => 'new' } )->as_array())->as_array();
# ( 'old', { key => 'new' }, 'new' )
xh( 'old', { key => 'old' } )->push(
xh( 'new', { key => 'new' } )->as_hash())->as_hash();
# ( { 0 => 'new' }, { key => 'new' } )
Options:
$xhash->reorder($refkey, @keys)
Reorders elements within the XHash relative to the reference element having key $refkey
, which must exist and will not be moved.
If the reference key appears in @keys
, the elements with keys preceding it will be moved immediately before the reference element. All other elements will be moved immediately following the reference element.
Only the first occurence of any given key in @keys
is considered - duplicates are ignored.
If any key is an arrayref, it is replaced with a sorted list of index keys.
Returns the XHash tiedref or object (whichever was used).
# Move some keys to the beginning of the XHash.
$xhash->reorder($xhash->first_key(), @some_keys,
$xhash->first_key());
# Move some keys to the end of the XHash.
$xhash->reorder($xhash->last_key(), @some_keys);
# Group numeric index keys in ascending order at the lowest one.
$xhash->reorder([]);
$xhash->remap(\%mapping)
$xhash->remap(%mapping)
Remaps element keys according to the specified mapping (a hash of $old_key => $new_key
). The mapping must map old keys to new keys one-to-one.
The order of elements in the XHash is unchanged.
$xhash->renumber(%options)
Renumbers all elements with an integer index (those returned by $xhash->keys(index_only => 1)
). The order of elements is unchanged.
Returns the XHash tiedref or object (whichever was used).
Options:
- from => $starting_index
-
Renumber from
$starting_index
instead of the default zero. - sorted => $boolean
-
This option is passed to
$xhash->keys()
.If set to true, keys will be renumbered in sorted sequence. This results in a "relative" renumbering (previously higher index keys will still be higher after renumbering, regardless of order in the XHash).
If false or not set, keys will be renumbered in XHash (or "absolute") order.
$xhash->traverse($path, options?)
This method traverses nested XHash trees. The path may be a simple scalar key, or it may be an array reference containing multiple keys along the path.
An undef
value along the path will translate to the next available integer index at that level in the path. A {}
at the end of the path forces auto-vivification of an XHash at the end of the path if one does not already exist there.
This method returns a reference to a hash containing the elements "container", "key", and "value". If the path does not exist, the container value with be undef
.
An empty path ([]
) is equivalent to a path of undef
.
Options:
- op
-
Specifies the operation for which the traversal is being performed (fetch, store, exists, or delete).
- xhash
-
Force the path to terminate with an XHash (for "fetch" paths ending in
{}
). - vivify
-
Auto-vivify missing intermediate path elements.
AUTHOR
Brian Katzung, <briank at kappacs.com>
BUG TRACKING
Please report any bugs or feature requests to bug-data-xhash at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-XHash. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Data::XHash
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
SEE ALSO
- Array::AsHash
-
An array wrapper to manage elements as key/value pairs.
- Array::Assign
-
Allows you to assign names to array indexes.
- Array::OrdHash
-
Like Array::Assign, but with native Perl syntax.
- Data::Omap
-
An ordered map implementation, currently implementing an array of single-key hashes stored in key-sorting order.
- Tie::IxHash
-
An ordered hash implementation with a different interface and data structure and without auto-indexed keys and some of Data::XHash's other features.
- Tie::Hash::Array
-
Hashes stored as arrays in key sorting-order.
- Tie::LLHash
-
A linked-list-based hash like Data::XHash, but it doesn't support the push/pop/shift/unshift array interface and it doesn't have automatic keys.
- Tie::StoredOrderHash
-
Hashes with items stored in least-recently-used order.
LICENSE AND COPYRIGHT
Copyright 2012 Brian Katzung.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.