felix
felix

Reputation: 23

How do I move in a tree to the next child?

I try to build a tree on my own. I start with an anonymous hash and created the first knot ("there"). From there on I want to create a child knot, but what I attempted didn't work.

use Data::Dumper;
$tree = {};
$tree->{'these'} = {};
$tree = $tree->{'these'};
$tree->{'are'} = {};
print Dumper $tree;

$tree = $tree->{'these'}; doesn't move $tree to the anonymous hash. The output is

$VAR1 = {
          'are' => {}
        };

but I wanted it to be

$VAR1 = {
          'these' => {
                     'are' => {}
                     }
        };

Any idea is very appreciated.

Upvotes: 2

Views: 114

Answers (2)

ikegami
ikegami

Reputation: 386361

Let's start with a look at the last two lines you wrote:

$tree->{'are'} = {};
print Dumper $tree;

After that, how can $tree possibly be a reference to a hash that contains only the key these as you say you want?

The problem is that you're trying to use $tree for two different things:

  • A reference to the root node.
  • A reference to the node to which you want to add elements.

Those two hashes/nodes aren't always the same, so we need two variables. In fact, I'll use three for completely clarity.

  • $tree, a reference to the root node.
  • $node the node we are creating.
  • $parent the node into which we want to insert.

We start by creating a root node and assign it to $tree

my $tree = {};

We don't want to lose track of the root node, so we'll never assign to $tree again. We can assign to elements of the hash referenced by $tree, though.

The next time we insert, we want to insert into the root node.

my $parent = $tree;

Now it's time to start adding new nodes.

my $node = {};
$parent->{these} = $node;

The next time we insert, we want to insert into the newly created node.

$parent = $parent->{these};

We insert again.

my $node = {};
$parent->{are} = $node;

And that's it! All together:

use strict;     # ALWAYS use this.
use warnings;   # ALWAYS use this.

use Data::Dumper qw( Dumper );

my $tree = {};
my $parent = $tree;

{
   my $node = {};
   $parent->{these} = $node;
   $parent = $parent->{these};
}

{
   my $node = {};
   $parent->{are} = $node;
   $parent = $parent->{are};
}

print(Dumper($tree));

If that's clear, we can simplify a bit.

use strict;     # ALWAYS use this.
use warnings;   # ALWAYS use this.

use Data::Dumper qw( Dumper );

my $tree = {};
my $parent = $tree;

$parent->{these} = {};
$parent = $parent->{these};

$parent->{are} = {};
$parent = $parent->{are};

print(Dumper($tree));

We can even take it a step further!

use strict;     # ALWAYS use this.
use warnings;   # ALWAYS use this.

use Data::Dumper qw( Dumper );

my $tree = {};
my $parent = $tree;

$parent = $parent->{these} = {};   # Assignments are performed right-to-left.
$parent = $parent->{are} = {};

print(Dumper($tree));

Upvotes: 2

GMB
GMB

Reputation: 222582

Consider:

use strict;
use warnings;
use Data::Dumper;

my $tree = {};
$tree->{these}->{are} = {};
print Dumper $tree;

Rationale: your original code keeps reassigning new values to $tree, overwriting the previously assigned value:

$tree->{'these'} = {};       # original assignment
$tree = $tree->{'these'};    # new assignment: now $tree is an empty hash ref
$tree->{'are'} = {};         # new assignment: now $tree contains { are => {} }

Here is another way to express your intent using another variable:

use strict;
use warnings;
use Data::Dumper;

my $tree = {};
my $child_tree = {};
$child_tree->{are} = {};
$tree->{these} = $child_tree;
print Dumper $tree;

Unrelated side note: always use strict; use warnings;!

Upvotes: 2

Related Questions