Printing keys based on Hash values in Perl - perl

I need to print keys based on vales in hash. Here is the code, I wrote
foreach $value (values %hash)
{
print "$value\t$hash{$value}\n";
}
Error: I can only print values, but not keys.
Any help will be greatly appreciated.
Thanks

Hashes are designed to be accessed by key, not by value. You need to loop over a list of keys, not values.
Then you can use the keys to access the associated values.
foreach my $key (keys %hash) {
my $value = $hash{$key};
say "$key = \t$value";
}

Try with:
for my $key (keys %hash) {
print "$key\t$hash{$key}\n";
}

print "$_\t$hash{$_}\n" for keys %hash;

One-liner:
map { print "$_\t$hash{$_}\n" } keys %hash;

I would probably use while and each if you want to iterate through keys and values:
while (my ($key, $value) = each %hash) {
say "$key -> $value";
}

The title requests to print key based on the value.
if your key and value in your harsh table should be one to one
foreach $key (keys %hash)
{
$r_hash{$hash{$key}}=$key;
}
....

if you want to access it by values, then define your hash as
$x = { 'x1' => [ 'one','x1']}
foreach ( values %$x )
{
foreach $m1 (#$_) {
print "$m1\n";
}
}
Notice you can get the key from value by second member of the value array.

Related

Extract data hash reference from perl array

I am new to perl. I am returning an array of references from a function. However I am lost as how I loop over the data.
sub whatever{
my %product;
my %resolution;
my #data = ();
push #data, \%product;
push #data, \%resolution;
return #data;
}
In the control sub module.
my #results = $whatever($dt_id);
$c->app->log->debug(Dumper(#results));
results
$VAR1 = {'IOP' => 'IOP'};
$VAR2 = {'4km' => '4km','9km' => '9km'};
I get the two hashes but how do I loop over them.
To return the two hashes seperately:
return (\%product, \%resolution);
To map over them:
my ($product, $resolution) = whatever(...);
for my $key (%$product) {
# do something with $product->{$key};
}
try this:
for my $hash_ref (#results) {
for my $key (keys %$hash_ref) {
say "key '$key' has value '$hash_ref->{$key}'";
}
}

Change first key of multi-dimensional Hash in perl

I have a multi-dimensional hash in perl and I would like to change the first key for a chosen value. For example, I have the hash
my %Hash1;
$Hash1{1}{12}=1;
$Hash1{1}{10}=1;
$Hash1{2}{31}=1;
$Hash1{3}{52}=1;
$Hash1{3}{58}=1;
$Hash1{4}{82}=1;
$Hash1{4}{154}=1;
Now I want to replace the value 3 in the first key with the value 300. After this I would get:
$Hash1{1}{12}=1;
$Hash1{1}{10}=1;
$Hash1{2}{31}=1;
$Hash1{300}{52}=1;
$Hash1{300}{58}=1;
$Hash1{4}{82}=1;
$Hash1{4}{154}=1;
I know I could create a new hash by scanning the original hash and doing the following:
my %Hash2;
foreach my $key1 (sort keys %Hash1) {
foreach my $key2 (keys %{ $Hash1{$key1} }) {
if($key1==3){
$Hash2{300}{$key2}=1;
} else {
$Hash2{$key1}{$key2}=1;
}
}
}
But is there a quicker way?
$Hash1{300} = $Hash1{3};
delete $Hash1{3};

Store and get values from Perl hash tables

I want to store names in hash or array, which are in format
(e.g apple<->banana , orange<->papaya).
And now I have half information like apple or papaya which I need to look in that hash table and get the full combination apple<->banana and store it in a variable... :)
Hope my question is clear actually i read few hash documents and every where it's mentioned to search with full name ... so I need to search with half name or 1st word.
Assuming your input file is like:
apple<->banana
orange<->papaya
Here is a way to do the job:
#!/usr/bin/perl
use strict;
use warnings;
my %corresp;
while(<DATA>) {
chomp;
my ($k, $v) = split/<->/,$_;
$corresp{$k} = $v;
}
my %reverse = reverse %corresp;
my $search = 'apple';
if (exists$corresp{$search}) {
say "$search = $corresp{$search}";
} elsif(exists$reverse{$search}) {
say "$search = $reverse{$search}";
} else {
say 'No match!';
}
__DATA__
apple<->banana
orange<->papaya
Try this one:
my %hash = (
'apple' => 'banana',
'orange' => 'papaya'
);
## the word is looking for
my $word = 'orange';
## checking using Key
if(defined($hash{$word})){
print "$word <=> $hash{$word}";
}
## checking using value
else{
## handling only one value, not all
my ($key) = grep { $hash{$_} eq $word } keys %hash;
print "$key <=> $hash{$key}" if $key;
}

Perl sorting hash by values in the hash

I think I have the right idea but there's some syntax/convention thing I'm messing up, because I get the error "Global symbol %timeHash requires explicit package name".
Code:
foreach $key (sort hashValueDescendingNum (keys(%timeHash))) {
print "\t$key\t\t $timeHash{$key}\n";
}
sub hashValueDescendingNum {
my $hash = shift;
$hash{$b} <=> $hash{$a};
}
Inline
foreach my $key (sort { $timeHash{$b} <=> $timeHash{$a} } keys %timeHash) {
print "\t$key\t\t $timeHash{$key}\n";
}
Using a custom sort function the way you are trying to will not work well, because then your sub would need to access the original hash.
foreach my $key (sort hashValueDescendingNum (keys(%timeHash))) {
print "\t$key\t\t $timeHash{$key}\n";
}
sub hashValueDescendingNum {
$timeHash{$b} <=> $timeHash{$a}; # Ew.
}
Instead you can abstract it further:
foreach my $key (sortedHashKeysByValueDescending(%timeHash)) {
print "\t$key\t\t $timeHash{$key}\n";
}
sub sortedHashKeysByValueDescending {
my %hash = #_;
my #keys = sort { $hash{$b} <=> $hash{$a} } keys %hash;
return #keys;
}
The code is not efficient because it passes around the %hash though, references would be better:
foreach my $key (sortedHashKeysByValueDescending(\%timeHash)) {
print "\t$key\t\t $timeHash{$key}\n";
}
sub sortedHashKeysByValueDescending {
my $hash = shift;
return sort { $hash->{$b} <=> $hash->{$a} } keys %$hash;
}
use List::UtilsBy qw( rev_nsort_by );
foreach my $key ( rev_nsort_by { $timeHash{$_} } keys %timeHash ) {
...
}

How to construct a hash of hashes

I need to compare two hashes, but I can't get the inner set of keys...
my %HASH = ('first'=>{'A'=>50, 'B'=>40, 'C'=>30},
'second'=>{'A'=>-30, 'B'=>-15, 'C'=>9});
foreach my $key (keys(%HASH))
{
my %innerhash = $options{$key};
foreach my $inner (keys(%innerhash))
{
print "Match: ".$otherhash{$key}->{$inner}." ".$HASH{$key}->{$inner};
}
}
$options{$key} is a scalar (you can tell be the leading $ sigil). You want to "dereference" it to use it as a hash:
my %HASH = ('first'=>{'A'=>50, 'B'=>40, 'C'=>30},
'second'=>{'A'=>-30, 'B'=>-15, 'C'=>9});
foreach my $key (keys(%HASH))
{
my %innerhash = %{ $options{$key} }; # <---- note %{} cast
foreach my $inner (keys(%innerhash))
{
print "Match: ".$otherhash{$key}->{$inner}." ".$HASH{$key}->{$inner};
}
}
When you're ready to really dive into these things, see perllol, perldsc and perlref.
I'm guessing you say "options" there where you mean "HASH"?
Hashes only store scalars, not other hashes; each value of %HASH is a hash reference that needs to be dereferenced, so your inner loop should be:
foreach my $inner (keys(%{ $HASH{$key} })
Or:
my %HASH = ('first'=>{'A'=>50, 'B'=>40, 'C'=>30},
'second'=>{'A'=>-30, 'B'=>-15, 'C'=>9});
foreach my $key (keys(%HASH))
{
my $innerhash = $HASH{$key};
foreach my $inner (keys(%$innerhash))
{
print "Match: ".$otherhash{$key}->{$inner}." ".$innerhash->{$inner};
}
}