Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: Hash/Array slice : how to exclude items?

by Corion (Patriarch)
on Jan 24, 2023 at 13:03 UTC ( [id://11149817]=note: print w/replies, xml ) Need Help??


in reply to Hash/Array slice : how to exclude items?

If this is only about the top-level items, I would create a shallow copy and delete the keys there (or only keep the "good" keys):

sub debug_hash( $hashref, $bad_keys = [qw[ schema logger ]] ) { my %output = %$hashref; delete @output{ @$bad_keys }; print Dumper \%output; } debug_hash( { logger => 'foo', payload => 'bar' } ); debug_hash( { schema => 'users', password => 'hunter2' }, ['schema', ' +password'] );

Replies are listed 'Best First'.
Re^2: Hash/Array slice : how to exclude items?
by haukex (Archbishop) on Jan 24, 2023 at 14:40 UTC
    I would create a shallow copy and delete the keys there

    An alternative:

    sub debug_hash ( $hashref, $bad_keys = [qw/ schema logger /] ) { delete local @$hashref{ @$bad_keys }; print Dumper $hashref; }
      delete local requires 5.12 (as mentioned in the link you provided, too, I just think it's worth mentioning here).

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      delete local looks promising, thanks haukex and ikegami. If only delete returned the remaining hash. Shouldn't this work?: print Dumper(do { delete local  @$hashref{ @$bad_keys }, $hashref} ); or this print Dumper(do { delete local  @$hashref{ @$bad_keys }; $hashref} ); My intention is to delete the elements of the local hash, pass that to Dumper and hopefully leave it untouched when Dumper returns.

      my @unwanted = qw( schema log ); my %hash = (schema=>1, log=>2, aa=>3); print Dumper(delete local @hash{ @unwanted }, \%hash); print Dumper(\%hash); $VAR1 = 1; $VAR2 = 2; $VAR3 = { 'aa' => 3 }; $VAR1 = { 'aa' => 3 };
      my @unwanted = qw( schema log ); my %hash = (schema=>1, log=>2, aa=>3); print Dumper(do { delete local @hash{ @unwanted }; \%hash }); print Dumper(\%hash); $VAR1 = { 'aa' => 3, 'log' => 2, 'schema' => 1 }; $VAR1 = { 'aa' => 3, 'log' => 2, 'schema' => 1 };

        delete returns the thing(s) deleted, not the things remaining after deletion, so that idea won't fly.

        The effect of local is undone at the end of the block (scope) in which it was done, so your proposed examples cannot work - the elements have already been restored by the time Dumper() gets a look at the hash.

        If you can put the Dumper() call inside the block, then it will work:

          print do { delete local @$hashref{ @$bad_keys }; Dumper($hashref) };

        For a complete example:

        % perl -we '%a=(schema=>1,log=>2,aa=>3); use Data::Dumper; print do { delete local @a{qw{ schema log }}; Dumper(\%a) }' $VAR1 = { 'aa' => 3 }; %
        > Shouldn't this work?:

        > print Dumper(do { delete local  @$hashref{ @$bad_keys }, $hashref} ); or this print Dumper(do { delete local  @$hashref{ @$bad_keys }; $hashref} );

        yes it's surprising.

        One needs to remember that local is protecting certain entries and not the whole hash (The hash could be a lexical variable, local wouldn't do anyway)

        Since you are returning a reference, you'll see the restored entries again after leaving the block.

        consider what's happening without delete

        DB<91> use Data::Dump qw/pp/ DB<92> ; {local @hash{qw/log schema/};say pp \%hash}; say pp \%hash { a => 1, b => 2, c => 3, log => undef, schema => undef } { a => 1, b => 2, c => 3, log => "l", schema => "s" }

        you can still have the desired effect by just returning a list or a new anonymous hash

        DB<96> say pp do {delete local @hash{qw/log schema/}; %hash }; say +pp \%hash ("a", 1, "c", 3, "b", 2) { a => 1, b => 2, c => 3, log => "l", schema => "s" } DB<97> say pp do {delete local @hash{qw/log schema/}; +{%hash} }; s +ay pp \%hash { a => 1, b => 2, c => 3 } { a => 1, b => 2, c => 3, log => "l", schema => "s" } DB<98>

        if you shy away from the overhead to return a new hash, just do the dumping inside the block.

        DB<99> ; {delete local @hash{qw/log schema/};say pp \%hash}; say pp +\%hash { a => 1, b => 2, c => 3 } { a => 1, b => 2, c => 3, log => "l", schema => "s" } DB<100>

        HTH! :)

        Cheers Rolf
        (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
        Wikisyntax for the Monastery

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11149817]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-04-24 06:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found