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

Hi,

I have a hashref, like so:
my $foo = { testing => bar, test => test2, something => test3 }
I know if it was just a simple hash, I could delete multiple fields with: delete @$foo{qw(testing something)} ..which would leave just "test" in there. However, I can't work out how to do it with a hashref. Any suggestions?

ATM I'm having to do a:

foreach (qw/fields here to delete/) { delete $foo->{$_}; }
..but my guess would be that using a single liner, would be more efficient (and cleaner ;))

TIA

Andy

Replies are listed 'Best First'.
Re: Remove multiple fields from hashref?
by kcott (Archbishop) on Mar 12, 2014 at 07:10 UTC

    G'day ultranerds,

    Just put braces around $foo in your hash slice. [That's not strictly correct — see Update (Clarification) below.]

    #!/usr/bin/env perl use strict; use warnings; my $foo = { testing => 'bar', test => 'test2', something => 'test3' }; delete @{$foo}{qw(testing something)}; use Data::Dump; dd $foo;

    Output:

    { test => "test2" }

    Update (Clarification)

    In your OP, you have:

    "I know if it was just a simple hash, I could delete multiple fields with: delete @$foo{qw(testing something)} ..."

    If that was a "simple hash" (e.g. %foo), then the detete statement would need to have "@foo", not "@$foo".

    I suspect having seen "simple hash", my eyes glossed over the $ before foo and some mental confusion ensued.

    So, the delete statement you showed would have worked fine for a hashref (e.g. $foo) but not for a hash (e.g. %foo); and, my statement, "Just put braces around $foo ...", wasn't strictly correct in that it didn't address your problem even though it was valid syntax which achieved the end result you were looking for.

    To quickly summarise the syntax for specifying a hash slice:

    • For a hash (e.g. %hash = (...)), use either @hash{...} or @{hash}{...}
    • For a hashref (e.g. $hashref = {...}), use either @$hashref{...} or @{$hashref}{...}

    While I typically write %$hashref, @$arrayref and even $#$arrayref, I do tend to use braces for anything more complex, including slices.

    [If you're interested, Perl Best Practices recommends putting braces around references in all of those (i.e. %{$hashref}, @{$arrayref} and $#{$arrayref}). Obviously, I don't follow all of the Perl Best Practices. :-)]

    -- Ken

Re: Remove multiple fields from hashref?
by Anonymous Monk on Mar 12, 2014 at 07:03 UTC
    references quick reference
    @regular ## deref @$ref ## deref @{ $hRef } @regular @{ $hRef }{ qw/ s l i c e / } @regular{ qw/ s l i c e / } delete @{ $hRef }{ qw/ s l i c e / } delete @regular{ qw/ s l i c e / }
      use Data::Dump; %f = 1..8; dd\%f; delete @f{1..4}; dd\%f; $f=\%f; delete @{$f}{1..8}; dd $f; __END__ { 1 => 2, 3 => 4, 5 => 6, 7 => 8 } { 5 => 6, 7 => 8 } {}
      Thanks - so I basically just need to de-def it before I can do anything? :)
        Never mind - I see what you mean - and it worked a charm. Thanks :)