in reply to Iteratively deep copying a data structure
It doesn't look very elegant.
Checking the reference type twice is not elegant. More importantly, it doesn't work since you only handle HASH (and not ARRAY and non-refs) at the outer level.
_iterative_copy( [ 'a' ] );
outputs
What's a ARRAY at script.pl line 12 main::_iterative_copy('ARRAY(0x15d5f18)') called at script.pl +line 47
Working code:
use strict; use warnings; use Data::Dumper qw( Dumper ); sub iterative_copy { my $root; my @src; my @dst; push @src, $_[0]; push @dst, \$root; while (@src) { my $src = shift(@src); my $dst = shift(@dst); if (not ref $src) { $$dst = $src; } elsif (ref $src eq "HASH") { $dst = ($$dst = {}); foreach my $key (keys %$src) { push @src, $src->{$key}; push @dst, \($dst->{$key}); } } elsif (ref $src eq "ARRAY") { $dst = ($$dst = []); foreach my $i (0..$#$src) { push @src, $src->[$i]; push @dst, \($dst->[$i]); } } else { Carp::croak "What's a " . ref $_ . "?" } } return $root; } { local $Data::Dumper::Indent = 0; my $d1 = [ [ 'a', 'b' ], { k1=>'v1', k2=>'v2' } ]; my $d2 = iterative_copy($d1); print(Dumper($d1), "\n"); print(Dumper($d2), "\n"); print($d1, " != ", $d2, "\n"); print($d1->[0], " != ", $d2->[0], "\n"); print($d1->[1], " != ", $d2->[1], "\n"); }
Output:
$VAR1 = [['a','b'],{'k2' => 'v2','k1' => 'v1'}]; $VAR1 = [['a','b'],{'k2' => 'v2','k1' => 'v1'}]; ARRAY(0x1ae0718) != ARRAY(0x1ae073c) ARRAY(0x15d5fd8) != ARRAY(0x1ae076c) HASH(0x15d6c98) != HASH(0x1ae0790)
Below is a more elegant version. It uses one array (@todo) instead of two (@src, @dst). However, it uses more memory.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Iteratively deep copying a data structure
by telcontar (Beadle) on Jun 09, 2007 at 21:11 UTC |