FYI: I do have a sample implementation which works. From the tests:

$data = { foo => 3, bar => [ qw/ this that 3 / ], 3 => undef, baz => { trois => 3, quatre => [ qw/ 1 2 3 4 / ], } }; ok $paths = path( $data, 3 ), 'Fetching paths for matching data should succeed'; my @expected = sort ( '{bar}[2]', '{baz}{trois}', '{baz}{quatre}[2]', '{foo}' ); $paths = [ sort @$paths ]; is_deeply $paths, \@expected, '... and we should be able to match complex data structures'; foreach my $path (@$paths) { is eval "\$data->$path", 3, '... and each element should have the correct value'; }

And the some rough code:

use Scalar::Util 'reftype'; my %path = ( ARRAY => \&_array_path, HASH => \&_hash_path, ); sub path { my ( $data, $search ) = @_; my $type = reftype $data; my $find_paths = $path{$type}; return $find_paths->( $data, $search ); } sub _array_path { my ( $data, $search ) = @_; my @paths; foreach my $i (0 .. $#$data) { my $item = $data->[$i]; my $type = reftype $item; my $current_index = "[$i]"; if ( !$type && $item eq $search ) { # XXX push @paths => $current_index; } elsif ( my $find_paths = $path{$type} ) { my @current_paths = map { "$current_index$_" } @{ $find_paths->( $item, $search ) }; push @paths => @current_paths; } } return \@paths; } sub _hash_path { my ( $data, $search ) = @_; my @paths; foreach my $key (keys %$data) { my $item = $data->{$key}; my $type = reftype $item; my $current_key = "{$key}"; if ( !$type && $item eq $search ) { # XXX push @paths => $current_key; } elsif ( my $find_paths = $path{$type} ) { my @current_paths = map { "$current_key$_" } @{ $find_paths->( $item, $search ) }; push @paths => @current_paths; } } return \@paths; }

The code itself works fine, but the tests show that using it (the string eval) seems really clumsy. It works fine for what I need, but still looking for a better approach (cleaner and faster).

Cheers,
Ovid

New address of my CGI Course.


In reply to Re: Efficient partial deep cloning by Ovid
in thread Efficient partial deep cloning by Ovid

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



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.