http://qs321.pair.com?node_id=178827

princepawn has asked for the wisdom of the Perl Monks concerning the following question:

In this node I was given an excellent suggestion by George_Sherston on how to handle a data processing issue. In summary, convert my HoH to an AoH.

I have now coded Data::Hash::Flatten to this end. And it works... however, I want to get rid of my global @Data::Hash::Flatten::flattened variable which keeps all the created records and instead simply use an array which is passed through the recursive calls and returned at the end.

Here is summary input and output of my module

my $a = { bill => { '5/27/96' => { 'a.dat' => 1, 'b.txt' => 2, 'c.lsp' + => 3 } \ }, jimm => { '6/22/98' => { 'x.prl' => 9, 'y.pyt' => 8, 'z.tc +l' => 7 } \ } } ; my @a = Data::Hash::Flatten->this($a, [qw(name date file)]); use Data::Dumper; print Dumper(\@a); $VAR1 = [ { 'hits' => 7, 'date' => '6/22/98', 'name' => 'jimm', 'file' => 'z.tcl' }, { 'hits' => 8, 'date' => '6/22/98', 'name' => 'jimm', 'file' => 'y.pyt' }, { 'hits' => 9, 'date' => '6/22/98', 'name' => 'jimm', 'file' => 'x.prl' }, { 'hits' => 3, 'date' => '5/27/96', 'name' => 'bill', 'file' => 'c.lsp' }, { 'hits' => 2, 'date' => '5/27/96', 'name' => 'bill', 'file' => 'b.txt' }, { 'hits' => 1, 'date' => '5/27/96', 'name' => 'bill', 'file' => 'a.dat' }

and here is my source code

sub this { my (undef, $href, $field, $depth, $flat_rec) = @_; @flattened = () unless defined($depth); if (ref $href) { my @key = keys %$href; # warn "ref $href succeeded. depth: $depth keys: @key, the ref:", D +umper($hre\ f); for my $key_i (0..$#key) { my $key = $key[$key_i]; # warn "KEY: $key"; $flat_rec->{$field->[$depth]} = $key; # warn "(depth $depth) flat_rec->{$field->[$depth]} = $key"; Data::Hash::Flatten->this($href->{$key}, $field, $depth+1, $flat +_rec, @fla\ ttened); } } else { $flat_rec->{$field->[$depth]} = $href; # warn "no more refs. we are at bottom. pushing:", Dumper($flat_rec +), "here i\ s href:", Dumper($href), "depth $depth"; use Storable qw(dclone); my $new_rec = dclone $flat_rec; push @flattened, $new_rec; } @flattened; }

edited: Tue Jul 2 14:36:31 2002 by jeffa - added reamore tag

Replies are listed 'Best First'.
Re: Extending and Preserving Array State through Recursive Function Calls
by broquaint (Abbot) on Jul 02, 2002 at 12:46 UTC
    This gets around the package variable issue
    package Data::Hash::Flatten; use Storable qw(dclone); sub this { my @args = ([], @_[1 .. $#_]); Data::Hash::Flatten->_flatten(@args); } sub _flatten { my (undef, $flattened, $href, $field, $depth, $flat_rec ) = @_; @$flattened = () unless defined($depth); if ( ref $href ) { my @key = keys %$href; for my $key_i ( 0 .. $#key ) { my $key = $key[$key_i]; $flat_rec->{ $field->[$depth] } = $key; Data::Hash::Flatten->_flatten($flattened, $href->{$key}, $field, $depth + 1, $flat_rec); } } else { $flat_rec->{ hits } = $href; my $new_rec = dclone $flat_rec; push @$flattened, $new_rec; } @$flattened; } package main; use Data::Dumper; my $a = { bill => { '5/27/96' => { 'a.dat' => 1, 'b.txt' => 2, 'c.lsp' => 3 } }, jimm => { '6/22/98' => { 'x.prl' => 9, 'y.pyt' => 8, 'z.tcl' => 7 } } }; my @a = Data::Hash::Flatten->this( $a, [qw(name date file)] ); print Dumper( \@a );
    Hackish, but effective. Perhaps a better way around this is to re-write it as a class with methods and properties as opposed as to a function tucked away in it's own package.
    HTH

    _________
    broquaint

    update: changed code in this to suck less (wasn't passing the correct args)

Re: Extending and Preserving Array State through Recursive Function Calls
by demerphq (Chancellor) on Jul 02, 2002 at 13:50 UTC
    A similar question was asked yesterday.

    I believe my answer there may be useful to you.

    Re: Global variables

    HTH

    Yves / DeMerphq
    ---
    Writing a good benchmark isnt as easy as it might look.