Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
How do you splice a hash? For example I have the following hash:
my %hash = ( 'foo' => [1,2,3], 'bar' =>[3,4,5]);
I want to extract only 'foo' hash
my $wanted = {'foo' => [1,2,3]};
And also destructing %hash. Because I need to process $wanted and then return them back again in %hash.

Replies are listed 'Best First'.
Re: Hash Splice
by GrandFather (Saint) on Sep 21, 2007 at 08:10 UTC

    If you really want to "slice" (not really "splice") your hash then you can:

    my %hash = ( 'foo' => [1,2,3], 'bar' =>[3,4,5]); my @wantedKeys = qw(foo); my %wanted; @wanted{@wantedKeys} = @hash{@wantedKeys};

    Perl is environmentally friendly - it saves trees
      Hi GP,

      I really mean "splice" not slice. And I really want to remove 'foo' in initial %hash. Is there a way to do it?
        use strict; use Data::Dumper; my %h = ( foo => 'bar', baz => 'weeble', ); my @remove = 'baz'; my %removed; @removed{ @remove } = delete @h{ @remove }; print Dumper \%h; print Dumper \%removed;
        Use the delete function to remove an element from a hash. Example: delete $hash{foo};

        If you only want to remove one of the elements from the anonymous array (say the second element) in the hash element 'foo', you can do this: delete $hash{foo}[1];

        BTW, to keep the values of the hash that you're deleting (in the %wanted hash), the delete function returns the key and value. Example: $wanted{foo} = delete $hash{foo}; Here's a complete example:

        my %wanted = (); my %hash = ( 'foo' => [1,2,3], 'bar' =>[3,4,5]); $wanted{foo} = delete $hash{foo}; print "Left-over:\n"; for $key (keys %hash) { print "$key, @{$hash{$key}}\n"; } print "Wanted:\n"; for $key (keys %wanted) { print "$key, @{$wanted{$key}}\n"; }
        Produces the following output:

        Left-over: bar, 3 4 5 Wanted: foo, 1 2 3
        Good luck!
Re: Hash Splice
by erroneousBollock (Curate) on Sep 21, 2007 at 07:27 UTC
    How do you splice a hash?
    I want to extract only 'foo' hash
    Something like:

      my $wanted = { foo => $hash{foo} };

    -David

Re: Hash Splice
by graff (Chancellor) on Sep 22, 2007 at 02:18 UTC
    The notion of "splicing" only applies to arrays, where elements are ordered in a numeric sequence; deleting a non-final element from an array requires that all higher-numbered elements be shifted, in order to keep the overall sequence contiguous, and that is what splice does.

    Since hashes are unordered, the notion of splicing does not a apply. An element (hash key) either exists or does not exist. If one exists and you want it to cease existing, you simply delete it.

      your right, and you can demonstrate this problem in part by converting the two hashes to lists, splicing them, and then converting them back, if you have any elements that have duplicate names will disappear and the one that came last will get the value and that's already error prone, and then you have the even-list checking and making sure the keys don't become values and vice-verse' by accident -- it can be VERY error prone... its better to just delete and set keys as needed then to do it this way, or merge to hashes, but arrays are like Christmas and hashes are like Easter, if you get what I mean.
Re: Hash Splice
by perlfan (Parson) on Sep 21, 2007 at 13:27 UTC
    A hash allows you to reference an item directly, so
    use Data::Dumper; %hash = ( 'foo' => [1,2,3], 'bar' =>[3,4,5]); my $wanted = {}; # create reference to anonymous hash $wanted->{foo} = $hash{foo}; # assignment print Dumper($wanted);