delete() on multi level hash

Discussion in 'Perl Misc' started by moritz.maisel@googlemail.com, Feb 23, 2007.

  1. Guest

    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;
    , Feb 23, 2007
    #1
    1. Advertising

  2. wrote:
    >
    > 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
    --
    Perl isn't a toolbox, but a small machine shop where you can special-order
    certain sorts of tools at low cost and in short order. -- Larry Wall
    John W. Krahn, Feb 23, 2007
    #2
    1. Advertising

  3. Paul Lalli Guest

    On Feb 23, 5:59 am, ""
    > 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
    Paul Lalli, Feb 23, 2007
    #3
  4. Guest

    Hi John and Paul!

    Thanks a lot for your detailed explanations!

    Best regards,
    Moritz
    , Feb 27, 2007
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    2
    Views:
    442
  2. pabbu
    Replies:
    8
    Views:
    720
    Marc Boyer
    Nov 7, 2005
  3. rp
    Replies:
    1
    Views:
    517
    red floyd
    Nov 10, 2011
  4. Srijayanth Sridhar
    Replies:
    19
    Views:
    614
    David A. Black
    Jul 2, 2008
  5. hymie!
    Replies:
    5
    Views:
    151
    Peter Scott
    Jun 15, 2004
Loading...

Share This Page