delete() on multi level hash

M

moritz.maisel

Hi,

how (if at all) is the behaviour of delete() defined for "multi-level-
hash-references"?

What I expected from the code at the bootom was:

$VAR1 = {
'y' => {
'8' => {
'c' => 3,
}
},
'w' => {
'' => {},
'6' => {
'a' => 1,
}
},
'x' => {
'7' => {
'b' => 2,
}
},
'z' => {
'9' => {
'd' => 4,
}
}
};

But I got:

$VAR1 = {
'y' => {
'' => {},
'8' => {
'c' => 3,
'foo' => 'y'
}
},
'w' => {
'' => {},
'6' => {
'a' => 1,
'foo' => 'w'
}
},
'x' => {
'' => {},
'7' => {
'b' => 2,
'foo' => 'x'
}
},
'z' => {
'' => {},
'9' => {
'd' => 4,
'foo' => 'z'
}
}
};

It works as expected if I copy the reference to a helper variable and
doing the delete on that, but I would like to understand the behaviour
in the described case ...

Does anybody have an explanation? Or a hint where to find one on the
net?

Thanks in advance,
Moritz

-----

#!/usr/bin/perl

use Data::Dumper;

$list = [
{ "foo" => "w", "bar" => "6" , "a" => 1 } ,
{ "foo" => "x", "bar" => "7" , "b" => 2 } ,
{ "foo" => "y", "bar" => "8" , "c" => 3 } ,
{ "foo" => "z", "bar" => "9" , "d" => 4 }
];

print Dumper $list;


foreach (@{$list}) {
$temp->{$_->{'foo'}}->{$_->{'bar'}} = $_;
delete($temp->{$_->{'foo'}}->{$_->{'bar'}}->{'bar'});
delete($temp->{$_->{'foo'}}->{$_->{'bar'}}->{'foo'});
}

print Dumper $temp;
 
J

John W. Krahn

how (if at all) is the behaviour of delete() defined for "multi-level-
hash-references"?

What I expected from the code at the bootom was:

$VAR1 = {
'y' => {
'8' => {
'c' => 3,
}
},

[ snip ]
};

But I got:

$VAR1 = {
'y' => {
'' => {},
'8' => {
'c' => 3,
'foo' => 'y'
}
},

[ snip ]
};

It works as expected if I copy the reference to a helper variable and
doing the delete on that, but I would like to understand the behaviour
in the described case ...

Does anybody have an explanation? Or a hint where to find one on the
net?

#!/usr/bin/perl

use Data::Dumper;

$list = [
{ "foo" => "w", "bar" => "6" , "a" => 1 } ,
{ "foo" => "x", "bar" => "7" , "b" => 2 } ,
{ "foo" => "y", "bar" => "8" , "c" => 3 } ,
{ "foo" => "z", "bar" => "9" , "d" => 4 }
];

print Dumper $list;


foreach (@{$list}) {
$temp->{$_->{'foo'}}->{$_->{'bar'}} = $_;

(Using the first element of @$list.)

$temp->{ "w" }->{ "6" } = { "foo" => "w", "bar" => "6", "a" => 1 };

delete($temp->{$_->{'foo'}}->{$_->{'bar'}}->{'bar'});

delete( $temp->{ "w" }->{ "6" }->{ 'bar' } );

Which leaves $temp with:

$temp->{ "w" }->{ "6" } = { "foo" => "w", "a" => 1 };

delete($temp->{$_->{'foo'}}->{$_->{'bar'}}->{'foo'});

Since you just deleted the key 'bar' this becomes:

delete( $temp->{ "w" }->{ "" }->{ 'foo' } );

Autovivification creates the "" key and there is no 'foo' under that key to
delete.


You probably want something like:

my $temp;
for ( @$list ) {
$temp->{ delete $_->{ foo } }{ delete $_->{ bar } } = $_;
}
print Dumper $temp;




John
 
P

Paul Lalli

On Feb 23, 5:59 am, "(e-mail address removed)"
foreach (@{$list}) {
$temp->{$_->{'foo'}}->{$_->{'bar'}} = $_;

Just to add to what John said - do you realize that after this
statement, both $_ and $temp->{w}->{6} are references to the *same*
hash? That changes to one affect the other?
delete($temp->{$_->{'foo'}}->{$_->{'bar'}}->{'bar'});

So when you remove the key 'bar' from the hash referenced by $temp-
{w}->{6}, you're also removing it from the hash referenced by $_.
delete($temp->{$_->{'foo'}}->{$_->{'bar'}}->{'foo'});

Which means at this point that the hash referenced by $_ does not have
the key 'bar' anymore. That's why you're getting the results you were
seeing.

Paul Lalli
 
M

moritz.maisel

Hi John and Paul!

Thanks a lot for your detailed explanations!

Best regards,
Moritz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top