isha has asked for the wisdom of the Perl Monks concerning the following question:
I have a hash having keys values pair as follow:
%myhash = { 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c'}
Now i want to get the keys where the value is 'a'.
How can i do this?
Re: How to get Keys from hash having same value?
by ysth (Canon) on Jan 07, 2008 at 05:55 UTC
|
@a_keys = grep { $myhash{$_} eq 'a' } keys %myhash;
| [reply] [d/l] |
Re: How to get Keys from hash having same value?
by merlyn (Sage) on Jan 07, 2008 at 06:06 UTC
|
%myhash = { 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c'}
isn't gonna work. You're creating a hashref (resulting in a single scalar) on the right, but assigning it to a hash (wanting a list) on the left. You should be consistent.
| [reply] [d/l] |
Re: How to get Keys from hash having same value?
by McDarren (Abbot) on Jan 07, 2008 at 05:54 UTC
|
Iterate through the keys of your hash, and look at the value of each one in turn.
for (keys %myhash) {
print "$_ eq a\n" if $myhash{$_} eq 'a';
}
| [reply] [d/l] |
|
Or, to avoid the extra hash lookups, iterate over key-value pairs using each.
my @as = ();
while (my ($key, $value) = each %myhash){
push @as, $key if $value eq 'a';
}
Update:
Is there a monk among us who can shorten this into a one-liner, similar to the grep keys examples we have seen?
It seems that each does not combine nicely with grep, map and their ilk. | [reply] [d/l] [select] |
|
%newhash = reverse do { my $hash = reverse %myhash; %hash };
To get the keys only (which are the values in the reversed hash:
@unique_keys = do { my $hash = reverse %myhash; values %hash };
update: oops, got it all wrong. It' about getting all keys where duplicate values are found.
As a single statement, formatted for readability
%myhash = (1 => 'a', 2=> 'b', 3=> 'a', 4=>'c',5 => 'b', 6 => 'a');
@k = do {
my %s;
map {
my $v=$_;
grep { $myhash{$_} eq $v} keys %myhash
} grep {$s{$_}++==1} values %myhash
};
print "$_ => $myhash{$_}\n" for @k;
__END__
6 => a
1 => a
3 => a
2 => b
5 => b
Ah well. Readability... ;-)
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] [select] |
|
I tried doing that, It is working.
use Data::Dumper;
%myhash = ( 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c', 5 => 'a', 6 => 'a', 7
+=>'b');
%newhash = map { ($_,$myhash{$_}) } grep { $myhash{$_} eq 'a'; } keys
+ %myhash ;
print Dumper \%newhash;
| [reply] [d/l] |
Re: How to get Keys from hash having same value?
by NetWallah (Canon) on Jan 07, 2008 at 07:08 UTC
|
If you are going to be making this query frequently, you may want to pre-build a "reverse lookup" hash:
my %h1 = qw (1 a 2 b 3 a 4 c);
my %h2; #Used for Value-to-key lookup
push @{$h2{$h1{$_}}},$_ for keys %h1; # Builds the reverse hash
print join( ",",@{$h2{a}}); # Lookup and print all keys in h1 that
+contain the value 'a'
# Prints: 1,3
"As you get older three things happen. The first is your memory goes, and I can't remember the other two... "
- Sir Norman Wisdom
| [reply] [d/l] |
Re: How to get Keys from hash having same value?
by Punitha (Priest) on Jan 07, 2008 at 06:10 UTC
|
Hi isha,
If you want to manipulate the simple hash, then your hash will be like this,
my %myhash = ( 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c');
To manipulate this simple hash, you can do like
use strict;
my %myhash = ( 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c');
for my $key (keys %myhash){
if($myhash{$key} eq 'a'){
print "KEY:$key\n";
}
}
But you created the hash as
my %myhash = { 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c'};
which is anonymous hash reference. To manipulate this hash reference, then you can do like
use strict;
my $myhash = { 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c'};
for my $key (keys %{$myhash}){
if(${$myhash}{$key} eq 'a'){
print "KEY:$key\n";
}
}
Punitha | [reply] [d/l] [select] |
Re: How to get Keys from hash having same value?
by ikegami (Patriarch) on Jan 07, 2008 at 09:57 UTC
|
If you're going to do this repeatedly (e.g. first find all the keys with value 'a', then find all keys with value 'b', etc.), then it might help to create a hash that maps the values to keys.
my %val_by_key = (
1 => 'a',
2 => 'b',
3 => 'a',
4 => 'c',
);
my %keys_by_val
foreach my $k (keys %vals_by_key) {
my $v = $vals_by_key{$k};
push @{ $keys_by_val{$v} }, $k;
}
# a: 1, 3
print('a: ', join(', ', @{$keys_by_val{'a'}}), "\n");
# a: 1, 3
# b: 2
# c: 4
foreach my $v (keys %keys_by_val) {
print("$v: ", join(', ', @{$keys_by_val{$v}}), "\n");
}
| [reply] [d/l] |
Re: How to get Keys from hash having same value?
by ambrus (Abbot) on Jan 08, 2008 at 07:40 UTC
|
| [reply] |
|
|