Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Getting a hash key based on the value 7

Status
Not open for further replies.

nfaber

Technical User
Oct 22, 2001
446
US
Hello all,

I know I can get a hash value based on the key as in:

Code:
my $var = $hash{$key};

but haow can I get a key when I know the value?

Thanks,

Nick
 
Nick, you can get more than one result like this

Code:
$var="value";
foreach (keys %hash) {
  if ($hash{$_} eq $var) {
    print "We got one $_\n";
  }
}

--Paul

cigless ...
 
Code:
while(($key, $value) = each(%hash)) {
     if ($value eq 'OK') {
          $var = $key;
          last;
     }
}


Michael Libeson
 
Thanks Paul. Here is what I am trying to do.

Code:
#
# Build a month lookup table
#
my %months = (
	"01" => "January"	,
	"02" => "February"	,
	"03" => "March"		,
	"04" => "April"		,
	"05" => "May"		,
	"06" => "June"		,
	"07" => "July"		,
	"08" => "August"	,
	"09" => "Spetember"	,
	"10" => "October"	,
	"11" => "November"	,
	"12" => "December"
);
#
# Determine the month and year for the report to run
#
$rpt_yr = $year;
if ($month == 01) {
	$rpt_month = 12;
	$rpt_yr = $rpt_yr - 1;
}
if ($month < 10) {
	$rpt_month = ("0" . ($month -1));
}else{
	$rpt_month = ($month - 1);
}

print (LOG "Data will be gathered for the month of $months{$rpt_month}\n\n");
#
#  Get the months for the 4 month chart
#
my $text_month1 = $months{$rpt_month};
push (@months, $text_month1);
if ($text_month1 eq "January") {
	$text_month2 = "December";
}else{
	$text_month2 = ($rpt_month - 1);
}
push (@months, $text_month2);
if ($text_month2 eq "January") {
	$text_month3 = "December";
}else{
	$rpt_month3 = ($rpt_month -2);
}
push (@months, $text_month3);
if ($text_month3 eq "January") {
	$text_month4 = "December";
}else{
	$rpt_month4 = ($rpt_month -3);
}
push (@months, $text_month4);
print (LOG "Text month array: @months\n\n");

I have the $rpt_month from the first snippet after populating the hash, now I want to account when rpt_month = 01 (January) change the month before to December. I need to be able to translate both ways. This could be avoided if I had a way to get the last 4 months in an array accounting for January to December transition. In other words if I was running the report for:

02 => February

the last four months in the array will be:

January
December
November
October

If running for:

03 => March

February
January
December
November

I hope that explains it.

Nick
 
Maybe I did not explain well. The thing is, I would just use the keys if I could decriment 09 and get 08, but I do not think that will work.

Nick
 
Code:
@months=('01','02','03','04',
         '05','06','07','08',
         '09','10','11','12');
print $months[-4];  # =>09

An array will allow you rotate around it's values using negative numbers, based on the number of indices in the array

This month is 03, found at index 2 [0,1,2]
Code:
$curr=2;
@last4months=($months[$curr-4],$months[$curr-3],$months[$curr-2],$months[$curr-1]);

Hope that gets you in the right direction
--Paul

cigless ...
 
Thanks Paul, but how do I set $curr in my code?
 
If its the system date you're looking for

Code:
$month=localtime()[4];
$month++;
$curr=$month;
Code:
@text  =("january", "february", "march",
         "april",   "may",      "june",
         "july",    "august",   "september",
         "october", "november", "december");
@months=('01','02','03','04',
         '05','06','07','08',
         '09','10','11','12');
@last4months=($months[$curr-4],$months[$curr-3],$months[$curr-2],$months[$curr-1]);
@last4text  =($text[$curr-4],$text[$curr-3],$text[$curr-2],$text[$curr-1]);

cigless ...
 
Thanks Paul, it worked here is my code

Code:
$curr=$rpt_month;
my @text  =("January", "February", "March",
         "April",   "May",      "June",
         "July",    "August",   "September",
         "October", "November", "December");
my @months=('01','02','03','04',
         '05','06','07','08',
         '09','10','11','12');
my @last4months=($months[$curr-4],$months[$curr-3],$months[$curr-2],$months[$curr-1]);
my @last4text  =($text[$curr-4],$text[$curr-3],$text[$curr-2],$text[$curr-1]);
print (LOG "Text month array: @last4months\n\n");

prints:

Code:
Text month array: 11 12 01 02

Thanks as well mlebison. Star for ya.

Nick
 
Code:
#!perl
use strict;
use warnings;

my @mnames = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my %mtable;
@mtable{map {sprintf "%02d",$_} (1..12)} = @mnames;
my $currmth = (localtime)[4] + 1;
my @last4 = map {sprintf "%02d", $_<1? $_+12: $_} ($currmth-4..$currmth-1);
print "$_ => $mtable{$_}\n" for reverse @last4;
Output:
Code:
02 => Feb
01 => Jan
12 => Dec
11 => Nov
 
Thanks Mike, but where were ya 4 hours ago?

[ponder]
 
I see you already got your answer and plenty more besides, but to your original question:

Hello all,
I know I can get a hash value based on the key as in:
my $var = $hash{$key};
but haow can I get a key when I know the value?

You can do this, you have built your hash:
Code:
my %months = (
    "01" => "January"    ,
    "02" => "February"    ,
    "03" => "March"        ,
    "04" => "April"        ,
    "05" => "May"        ,
    "06" => "June"        ,
    "07" => "July"        ,
    "08" => "August"    ,
    "09" => "Spetember"    ,
    "10" => "October"    ,
    "11" => "November"    ,
    "12" => "December"
);

now:

Code:
my %months_reversed = reverse %months;
print "The key for June is :$months_reversed{'June'}";

which may not have solved your problem but can be filed away for future reference. ;)
 
Thanks Kevin, if I new that I probably never would have needed to start this thread.

Nick
 
I have a question for PaulTEG et all on this thread. While the months transition well with Paul's code, I need a way to also transition the year when the month transitions from 1 (Jan) back to 12 (Dec).

Any help is appriciated.

 
What date formats are you working on?
Can you give a more detailed explanation of your requirements?

--Paul

cigless ...
 
Paul,

Here is what is happening. While the code you gave me handles the transition nicely for my 4 month chart,
I need a way to transition the year along with it. To remind you, here is the code I am using to get the months for
the 4 month chart:

Code:
#
# Get the start time and date. Print to logfile.
#
my ($sec, $min, $hr, $day, $month, $year, $weekday, $dayofyr, $junk_yuk) = localtime(time);
$month++;
if ($hr		< 10) {$hr	= "0" . $hr;}
if ($min	< 10) {$min	= "0" . $min;}
if ($sec	< 10) {$sec	= "0" . $sec;}
if ($month	< 10) {$month	= "0" . $month;}
if ($day	< 10) {$day	= "0" . $day;}
$year = $year + 1900;
#
# Determine the month and year for the report to run
#
my $rpt_yr = $year;
if ($month == 01) {
	$rpt_month = 12;
	$rpt_yr = $rpt_yr - 1;  # PAUL, THIS WAS MY FIRST BRUSH AT HANDLING THE YEAR TRANSITION NO GOOD!
}
if ($month < 10) {
	$rpt_month = ("0" . ($month -1));
}else{
	$rpt_month = ($month - 1);
}
#
# Build a month lookup table
#
my %months = (
	"01" => "January"	,
	"02" => "February"	,
	"03" => "March"		,
	"04" => "April"		,
	"05" => "May"		,
	"06" => "June"		,
	"07" => "July"		,
	"08" => "August"	,
	"09" => "Spetember"	,
	"10" => "October"	,
	"11" => "November"	,
	"12" => "December"
);
print (LOG "Data will be gathered for the month of $months{$rpt_month}\n\n");
#
#  Get the months for the 4 month chart
#
my $curr=$rpt_month;
my @text	=("January", "February", "March",
			"April",   "May",      "June",
			"July",    "August",   "September",
			"October", "November", "December"
);
my @months	=('01','02','03','04',
			'05','06','07','08',
			'09','10','11','12'
);
my @last4months=($months[$curr-4],$months[$curr-3],$months[$curr-2],$months[$curr-1]);
my @last4text  =($text[$curr-4],$text[$curr-3],$text[$curr-2],$text[$curr-1]);
print (LOG "Months for 4 month chart: $last4months[0],$last4months[1],$last4months[2],$last4months[3]\n\n");
$rpt_month = $last4months[3];

I was running my program and getting ticket counts for each month and not accounting for the year. Here is that code:

Code:
################################################################################################
#
# Count open, closed and backlog tickets for each month of the 4 months chart. We will use these
# for the one months charts as well.
#		
################################################################################################
#
# Closed tickets for last 4 months
#
if ($close_month eq $last4months[0]) {
	$closed_cnt{$last4months[0]}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	#print CLOSE0 "$_\n";
}
if ($close_month eq $last4months[1]) {
	$closed_cnt{$last4months[1]}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	#print CLOSE1 "$_\n";
}
if ($close_month eq $last4months[2]) {
	$closed_cnt{$last4months[2]}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	#print CLOSE2 "$_\n";
}
if ($close_month eq $rpt_month) {
	$closed_cnt{$rpt_month}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	#print CLOSE3 "$_\n";
}

This was not working as the code was counting tickets for this year AND last year (ie: May 2005 and May 2004). This was not
what I wanted so I added logic to exclude anything but the year the report is running for. Here is the modified code:

Code:
#
# Closed tickets for last 4 months
#
if (($close_month eq $last4months[0]) && ($close_year eq $rpt_yr)) {
	$closed_cnt{$last4months[0]}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	print CLOSE0 "$_\n";
}
if (($close_month eq $last4months[1]) && ($close_year eq $rpt_yr)) {
	$closed_cnt{$last4months[1]}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	print CLOSE1 "$_\n";
}
if (($close_month eq $last4months[2]) && ($close_year eq $rpt_yr)) {
	$closed_cnt{$last4months[2]}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	print CLOSE2 "$_\n";
}
if (($close_month eq $rpt_month) && ($close_year eq $rpt_yr)) {
	$closed_cnt{$rpt_month}++;
	# Uncomment the line below to dump the tickets counted for this count to a file
	print CLOSE3 "$_\n";
}

That takes care of when all the months fall in the same year, but what happens when I run the report next January
and the months transition from 01 (Jan) to 12 (Dec) for my 4 month chart but the year does not. The $rpt_yr
will still be 06 so if loop 1 is January

if (($close_month eq $last4months[0]) && ($close_year eq $rpt_yr)

no problem as $last4months[0] is 01, $close_year is 06 and $rpt_yr is 06.

But what about the transition back to December in the next loop:

if (($close_month eq $last4months[1]) && ($close_year eq $rpt_yr))

Here ticket $closed_month =12 and $last4months[1] equals 12 as well, no problem

but $close_year will = 05 and $rpt_yr will = 06 and the condition will not pass although I want it to.

I hope that explains it.

Thanks,

Nick
 
not sure if this is robust enough for your needs but it might work:

Code:
if (($close_month eq $last4months[1]) && ($close_year eq $rpt_yr) [b]|| $close_year == ($rpt_yr-1)[/b]))

also, you really should be comparing numbers in numeric context, not string context:

$close_month eq $last4months[1]

looks like it should be:

$close_month == $last4months[1]
 
Nick,
Something like this might work
Code:
my @last4months=($months[$curr-4],$months[$curr-3],$months[$curr-2],$months[$curr-1]);
[COLOR=red]$ly = 0; #init var
foreach (@last4months) {  # iterate over last 4 months
  if ($_ >= 10) {         # if its greater than oct, it was last year
    $last4years[$ly]=$year-1;
  } else {                # else its this year
    $last4years[$ly]=$year;
  }
  $ly++;                  #increase counter
}  
[/color]

HTH
--Paul

cigless ...
 
Kevin,

Thanks for the reply but wouldn't that be the same result as:

if ($close_month eq $last4months[0])

Meaning that if there was NO transition in months (ie: Feb, Mar, Apr, May) I would still get the tickets for May 04 AND May 05?

Nick
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top