telcontar has asked for the wisdom of the Perl Monks concerning the following question:
This works quite well. But let us assume, for the sake of the argument, that this should be implementet iteratively, not recursively.sub _copy { my $this = shift; if (not ref $this) { $this } elsif (ref $this eq "HASH") { +{map { $_ => _copy($this->{$_})} keys %$this} } elsif (ref $this eq "ARRAY") { [map _copy($_), @$this] } elsif (ref $this eq "CODE") { # do some processing here, the following is a # placeholder 'CODEREF' } else { Carp::croak "What's a " . ref $_ . "?" } }
It doesn't look very elegant. Can this be implemented more efficiently? I ask for enlightenment, for the purpose of understanding how to implement this sort of thing iteratively. One can easily imagine where using recursion on a very large data structure would use up a lot of memory.sub _iterative_copy { my $this = shift; my @pile = $this; my $this_new = {}; my $root = $this_new; my @pile_new = $this_new; while (defined($this = shift @pile)) { $this_new = shift @pile_new; if (ref $this eq "HASH") { for (keys %$this) { if (ref (my $v = $this->{$_})) { if (ref $v eq "HASH") { $this_new->{$_} = {} } elsif (ref $v eq "ARRAY") { $this_new->{$_} = [] } elsif (ref $v eq "CODE") { # do some processing here, # the following is a placeholder $this_new->{$_} = "CODEREF" } else { Carp::croak "What's a " . ref $v } unshift @pile, $v; unshift @pile_new, $this_new->{$_}; } else { $this_new->{$_} = $v } } } # quietly ignore coderefs, # they are dealt with in the inner loop elsif (ref $this ne "CODE") { Carp::croak "What's a " . ref $this } } $root;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Iteratively deep copying a data structure
by ikegami (Patriarch) on Jun 09, 2007 at 12:08 UTC | |
by telcontar (Beadle) on Jun 09, 2007 at 16:16 UTC | |
|
Re: Iteratively deep copying a data structure
by ikegami (Patriarch) on Jun 09, 2007 at 19:20 UTC | |
by telcontar (Beadle) on Jun 09, 2007 at 21:11 UTC |