Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

comment on

( [id://3333] : superdoc . print w/replies, xml ) Need Help??
If your hash structure is always HoHoHo... -- i.e. no arrays, just hashes -- then the first trick you need to nail down is a way to distinguish between terminal nodes and non-terminal nodes in your tree.

Based on your examples, I'd guess that the easiest way to do this is by using your actual strings only as hash keys, never as values assigned to keys. The value of a hash element would always be a hash ref; non-terminal nodes would contain hash refs with one or more keys, whereas a terminal node would contain an empty hashref. The point here is that hash value is either a simple scalar or else it's a reference -- it can't be both.

Here's a way you could take hyphen-delimited strings to create an abitrarily deep / arbitrarily wide tree structure:

use strict; use warnings; use Data::Dumper; sub load_hash { my ( $href, $path ) = @_; my @path = split /-/, $path; my $key = shift @path; while ( @path and exists( $$href{$key} )) { $href = $$href{$key}; $key = shift @path; } if ( ! exists( $$href{$key} )) { # there's a new key in this path $$href{$key} = {}; # so create a new hashref for it load_hash( $$href{$key}, join( "-", @path )) if ( @path ); # recurse if this key/node is non-terminal } # otherwise, do nothing -- the path already exists in the structure } sub trace_paths # look for paths to a chosen node (hash key) { my ( $href, $aref, $node, $path ) = @_; $path ||= ''; my @keys = keys %$href; if ( grep /^$node$/, @keys ) { push @$aref, ( $path ) ? "$path-$node" : $node; } for my $key ( @keys ) { my $nxt_path = ( $path ) ? "$path-$key" : $key; trace_paths( $$href{$key}, $aref, $node, $nxt_path ) if ( scalar keys %{$$href{$key}} ); } } my @strings = qw/one-foo-bar-baz one-foo-zuz two-fump-zill two-fizz-foo/; my %hash; load_hash( \%hash, $_ ) for ( @strings ); print Dumper( \%hash ); my @found; trace_paths( \%hash, \@found, 'foo' ); print Dumper( \@found );
(updated to fix an annoying initial dash in @found values)

Now, if you really want the structure to hold scalar values as well as hash keys, you'll need to reserve one or more "special keys" that you can use for storing strings or numbers instead of lower-level hash refs. These special keys need to be strings that will never occur as data (nodes in the structure), and the load_hash and/or trace_paths subs would need an extra line or two of code to use them as needed.

In reply to Re: seeking in hash data structure by graff
in thread seeking in hash data structure by Maze

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.