Re: Consise way to filter out keys with undef values from a hash slice?
by choroba (Cardinal) on Jun 01, 2020 at 20:21 UTC
|
What about grepping the keys even before the undef values are created?
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my %args = (profile => 'foo');
my %ta = %args{ grep exists $args{$_}, qw( profile user password ) };
print Dumper \%ta;
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [d/l] [select] |
Re: Consise way to filter out keys with undef values from a hash slice?
by davido (Cardinal) on Jun 02, 2020 at 14:59 UTC
|
my %args = (profile => 'foo');
my %ta = map {defined($args{$_} ? ($_ => $args{$_}) : ()} qw(profile u
+ser password);
If a map iteration returns an empty list, nothing gets added to the recipient's list. I don't usually like making map behave like grep, but in this case it seems a reasonable fit.
grep behavior can be provided by map by adding a Boolean test and a conditional return value.
my @array = grep {COND} LIST;
my @array = map {COND ? $_ : ()} LIST
| [reply] [d/l] [select] |
Re: Consise way to filter out keys with undef values from a hash slice?
by LanX (Saint) on Jun 01, 2020 at 21:16 UTC
|
This
>
grep { $args{$_ } } keys %ta;
Will also delete all false values like 0 or "" . You rather want to test on definedness and not truth
This keys on a slice
>
keys %args{'profile', 'user', 'password'};
Is over complicated and doesn't make sense.
You obviously just want the list of keys directly
'profile', 'user', 'password'
But I concur with choroba that using exists right from the beginning is the cleanest way, since undef could be a legal value.
edit
There is - unfortunately - no "slice when exists" operator in Perl.
Otherwise (ab)using hashes for set operations like intersections would be trivial.
| [reply] [d/l] [select] |
|
On a side note,
I was surprised that the following is even legal syntax. I only knew slicing lists with @
>
%args{'profile', 'user', 'password'};
Turns out it was introduced with 5.20 and returns a list of key/value pairs.
| [reply] [d/l] |
|
%a_b = map {exists $b{$_} ? ($_ => $b{$_}) : ()} keys %a;
Greetings, -jo
$gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
| [reply] [d/l] |
|
| [reply] |
Re: Consise way to filter out keys with undef values from a hash slice?
by kcott (Archbishop) on Jun 02, 2020 at 09:13 UTC
|
G'day nysus,
"Is there a good, more perlish way of pulling this off?"
In the absence of any information about wanting to capture the deleted keys,
I'd probably just do this:
delete @ta{grep !defined $ta{$_}, keys %ta};
I'm not sure if the way you've constructed %ta is really what you intended;
however, with Perl 5.30.0 I get no errors or warnings:
$ perl -Mstrict -Mwarnings -E '
my %args = (profile => "foo");
my %ta = %args{qw{profile user password}};
say "BEFORE:";
say for keys %ta;
delete @ta{grep !defined $ta{$_}, keys %ta};
say "AFTER:";
say for keys %ta;
'
BEFORE:
profile
password
user
AFTER:
profile
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
| [reply] |
|
|
Re: Consise way to filter out keys with undef values from a hash slice?
by AnomalousMonk (Archbishop) on Jun 01, 2020 at 21:32 UTC
|
... filter out undefined values ... [emphasis added]
My take is that keys with undefined values (either because non-existent or undef) are to be filtered out. One way:
c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le
"my %args = ('profile' => 'foo', 'xyzzy' => undef, 'status' => 0);
my %ta =
map { defined $args{$_} ? ($_ => $args{$_}) : () }
qw(profile password xyzzy status)
;
dd 'filtered', \%ta;
dd 'original', \%args;
"
("filtered", { profile => "foo", status => 0 })
("original", { profile => "foo", status => 0, xyzzy => undef })
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
Here a concise way for cleaning up afterwards:
$h{$_} // delete $h{$_} for keys %h
Unfortunately the even shorter approach doesn't work with deleting aliases
$_ // delete $_ for values %h
| [reply] [d/l] [select] |
Re: Consise way to filter out keys with undef values from a hash slice?
by tybalt89 (Monsignor) on Jun 01, 2020 at 22:31 UTC
|
#!/usr/bin/perl
use strict; # https://perlmonks.org/?node_id=11117569
use warnings;
my %args = (profile => 'foo');
my %ta = %args{ grep defined $args{$_}, 'profile', 'user', 'password'
+};
use Data::Dump 'dd'; dd \%ta;
| [reply] [d/l] |