Re: grep for hash?
by Corion (Patriarch) on Jul 07, 2009 at 11:48 UTC
|
Why use grep if you're not returning a list?
I use grep to create the list of keys and then use map to conver the keys into key/value pairs, which I then assign to the new hash:
my %new_hash = map { $_ => $original_hash{$_} } grep {/foo/} keys %ori
+ginal_hash;
| [reply] [d/l] |
Re: grep for hash?
by jwkrahn (Monsignor) on Jul 07, 2009 at 11:48 UTC
|
my %new_hash = map /$my_regexp/ ? ( $_ => $original_hash{ $_ } ) : (),
+ keys %original_hash;
| [reply] [d/l] |
Re: grep for hash?
by Fletch (Bishop) on Jul 07, 2009 at 12:49 UTC
|
use YAML::Syck qw( Dump );
my %orig = qw( a 1 b 2 c 3 d 4 e 5 f 6 );
my %new;
{
my @keys;
@new{ @keys } = @orig{ @keys = grep /[adf]/, keys %orig };
}
print Dump( { orig => \%orig, new => \%new } ), "\n";
exit 0;
__END__
---
new:
a: 1
d: 4
f: 6
orig:
a: 1
b: 2
c: 3
d: 4
e: 5
f: 6
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] [d/l] |
|
That needlessly makes operand evaluation order relevant. Change
my @keys;
@new{ @keys } = @orig{ @keys = grep /[adf]/, keys %orig };
to
my @keys = grep /[adf]/, keys %orig;
@new{ @keys } = @orig{ @keys };
and you have simpler, clearer code. | [reply] [d/l] [select] |
|
I was surprised that this not only works, but also does not complain if strictures are added to the code. The code looks ingenious, but I wonder about two aspects: First, you are accessing a list one time as a hash via %NAME, and then the same list as an array, via @NAME. Is this considered accepted practice? Honestly, I hadn't expected it to work with lexically scoped variables, and I'm not sure whether this trick (if I can call it like this) will remain with later Perl versions.
A more serious problem is the line
@new{ @keys } = @orig{ @keys = grep /[adf]/, keys %orig };
where you rely on the fact that @keys gets its value first (from the grep) before it is used to form a slice for @new. I think this is undefined behaviour, isn't it?
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] [select] |
|
All of the references are to the hashes %new and %old; the leading @ and curlies is just the way you name slices. The only array involved in the whole thing is @keys.
As for relying on the ordering, I think it's pretty safe to count that the rvalue will be computed and available before the lvalue is populated with it.
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] [d/l] [select] |
|
|
|
Re: grep for hash?
by Anonymous Monk on Jul 07, 2009 at 11:45 UTC
|
Not me
my %new = map { $_ => $orig{$_}; } grep {/$my_regexp/ } keys %orig; | [reply] [d/l] |
Re: grep for hash?
by poolpi (Hermit) on Jul 07, 2009 at 12:38 UTC
|
use strict;
use warnings;
use Data::Dumper;
my $orig = { 'foo' => 2, 'bar' => 4, 'boo' => 1, 'zar' => 5 };
my $dest;
map { /oo/ and $dest->{$_} = $orig->{$_} } keys %$orig;
print Dumper $dest;
__END__
Output:
$VAR1 = {
'boo' => 1,
'foo' => 2
};
hth, PooLpi
| [reply] [d/l] |
|
| [reply] |
|
Should be :D
/oo/ and $dest->{$_} = $orig->{$_} for keys %$orig;
| [reply] [d/l] |
|
$dest->{$_} = $orig->{$_} for grep /oo/, keys %$orig;
There's no need to twist one's mind to process the parent's expression.
| [reply] [d/l] |
Re: grep for hash?
by LanX (Saint) on Jul 07, 2009 at 14:54 UTC
|
This is such a frequently reinvented wheel! 8)
IMHO something like hgrep() or hmap() should be somewhere in the core-moduls... with a code-prototype it's easy to accomplish.
Anyway TIMTOWTDI:
Without explicit grep
%hash_2= map { /regex/ ? ( $_ , $hash_1{$_} )
: ()
} keys %hash_1;
Hashslice:
my @keys = grep { /regex/ } keys %hash_1;
@hash_2{@keys} = @hash_1{@keys};
http://www.perl-community.de/bat/poard/message/120873
| [reply] [d/l] [select] |