CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
How to Access all the values of multilevel hash

 

First page Previous page 1 2 Next page Last page  View All


Laurent_R
Veteran / Moderator

Nov 17, 2014, 11:00 AM

Post #26 of 30 (6210 views)
Re: [Tejas] How to Access all the values of multilevel hash [In reply to] Can't Post


Code
if (!exists $etid_mapping_hash{$key}) {       #if the key doesnt exist this is getting called, Is this the right thing to implement in my code?   
die "Invalid data\n";
}
if (!defined $etid_mapping_hash{$key} #I dont this this can be used ,as it creates a key and sets it to undef?
or ref $etid_mapping_hash{$key} ne 'ARRAY'
...

No, using just one key will not autovivify keys in the above code, whether you use exists or defined. As I explained, autovivification occurs in such context only for nested hashes (or arrays), where the keys below the last one will get created.


Code
print "autovivifies \n" if defined $h{a}{b}{c}

will autovivify keys a and b, but not c, if they don't exist. All the keys will be created except the last one (except c in the example). Now that you have a flat hash, you use only one key, so there is no danger of autovivification in a test for existence or definedness with your flat hash.

Using exists or defined does not make a difference in terms of autovivification, but they have a different semantic meaning that you should be aware of. For example, if I have this:


Code
$hash{$key} = undef; 
print "Exists \n" if exists $hash{$key} ; # prints "Exists"
print "Defined \n" if defined $hash{$key} ; # prints nothing

In other word, the container $hash{$key} has been created and exists, but its content (the value associated with the key) is not defined.

There are numerous cases where using one or the other does not make any difference, but there are also numerous cases where this apparently subtle difference is in fact of paramount importance and may make the difference between a program that works and one that does not.

So you really have to think about what you really want to check. If you want to print the content of the hash for the given key, then a check with defined is probably what you need.

An additional point: are you sure that you want to die if $etid_mapping_hash{$key} is not defined? If you do die, then you don't care about possible autovivification just prior to existing the program.

On a different subject, I do not see how this line:

Code
print "Write empty row to Excel\n";

could give you an undefined value error. Please post the real code.

Please explain what you are really trying to do, I really do not think that your 300 hash entries really make sense, there must be a better way, but I can't suggest any if I do not know the purpose.


Tejas
User

Nov 17, 2014, 11:07 AM

Post #27 of 30 (6208 views)
Re: [Laurent_R] How to Access all the values of multilevel hash [In reply to] Can't Post

Thanks

The only reason why iam creating hash entries is to check whether the input I get from a file belongs to settle or revenue or refund
Unlike what I have posted in post 20 , all the hash entries are unique

Because I have to print different sections in excel sheet
I had to create so many entires and depending on the entries Iam created my one more hash and iam checking these new hahses one by one and printing them to exce

Code
while (my $gl_line = <gl_file>)  
{
chomp($gl_line);
my ($_company_code,$transaction_document_amount,$subledger_source,$source_system,$automated_manual,$categorized) =split '\|', $gl_line;
# Populate the Revenue , Refunds and Settle Hash for Retail Companies
if($_company_code eq '04'|| $_company_code eq '3S'|| $_company_code eq '2R'||$_company_code eq '06'||$_company_code eq '79'){
if($revenue_hash{$_company_code}{$subledger_source}{$categorized}){
$retail_revenue_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
elsif($refund_hash{$_company_code}{$subledger_source}{$categorized}){
$retail_refunds_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
elsif($settle_hash{$_company_code}{$subledger_source}{$categorized}){
$retail_settlements_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}

elsif($_company_code eq '2Y') {
if($revenue_hash{$_company_code}{$subledger_source}{$categorized}){
$non_retail_revenue_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
elsif($refund_hash{$_company_code}{$subledger_source}{$categorized}){
$non_retail_refunds_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;

}
elsif($settle_hash{$categorized}){
$non_retail_settlements_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
}

}


If u can see the if condition iam just trying to check if it's true
If yes iam creating a hash entry to its type retail, refund or settlement


(This post was edited by Tejas on Nov 17, 2014, 11:11 AM)


Laurent_R
Veteran / Moderator

Nov 17, 2014, 12:04 PM

Post #28 of 30 (6199 views)
Re: [Tejas] How to Access all the values of multilevel hash [In reply to] Can't Post

I still don't understand what you are trying to do and can't help, although I really think your hash with 300 entries is probably useless and what you are trying to do with it could be better done in a different way.

On a different subject, when I see that:

Code
   if($_company_code eq '04'|| $_company_code eq  '3S'|| $_company_code eq '2R'||$_company_code eq '06'||$_company_code eq '79'){   
if($revenue_hash{$_company_code}{$subledger_source}{$categorized}){
$retail_revenue_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
elsif($refund_hash{$_company_code}{$subledger_source}{$categorized}){
$retail_refunds_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
elsif($settle_hash{$_company_code}{$subledger_source}{$categorized}){
$retail_settlements_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}

elsif($_company_code eq '2Y') {
if($revenue_hash{$_company_code}{$subledger_source}{$categorized}){
$non_retail_revenue_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
elsif($refund_hash{$_company_code}{$subledger_source}{$categorized}){
$non_retail_refunds_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;

}
elsif($settle_hash{$categorized}){
$non_retail_settlements_hash{"$_company_code|$automated_manual|$subledger_source|$source_system|$categorized"} += $transaction_document_amount;
}
}

there is an alarm in my brain which says: "Replication of code. Something must be wrong."

Rather that having almost the same code duplicated, you could select a hash ref depending on the company and then have the rest of the code only once. Something like this:


Code
if ($_company_code eq '2Y') { 
$retail_hash_ref = \$non_retail_revenue_hash;
} else {
$retail_hash_ref = \$retail_revenue_hash;
}

Then the rest of the code would be the same for all kinds of companies, just using hash refs instead of hashes, but no need to duplicate code. I know this is a bit simplified compared to what you have, but I hope you get the idea.

You could even build a hash with all the hash refs for each company, that would probably lead to even simpler code.

Code
my %retail =  
(2Y => \$non_retail_revenue_hash,
04 =>\$retail_revenue_hash,
# etc...
);

Then you use this hash find the hash ref where to store your values.


BillKSmith
Veteran

Nov 17, 2014, 12:26 PM

Post #29 of 30 (6197 views)
Re: [Tejas] How to Access all the values of multilevel hash [In reply to] Can't Post

I am responding to your comments in post #23.

First, I want you to realize that there are five possible situations, not just the two that you intend. It is necessary to identify and handle each of then correctly. My code correctly isolates each one. The action that I specify represents my best guess. You know better than I.

You should have simulated each one of these situations by uncommenting the corresponding declaration.


Quote
if (!exists $etid_mapping_hash{$key}) { #if the key doesnt exist this is getting called, Is this the right thing to implement in my code?


Maybe not, your call!


Quote
if (!defined $etid_mapping_hash{$key} #I dont this this can be used ,as it creates a key and sets it to undef?


Remember, The order of the tests is important. We already know that the key exists.


Quote
#Are below two statememt's correct in my code.?


Yes, but only after the other possibilities are handled



Quote
print "Write data to Excel\n"; # Only If its an array it prints


The previous test assures us that it is an array. This test assures us that the array contains atleast one element.



Quote
print "Write empty row to Excel\n"; #If not an array , prints empty , but it is throwing cant use an undefined value as an array reference if the key isnt defined, so this part probably cant be used


This is the exactly the same error you had yesterday for exactly the same reason. My code for the missing key would have handled the problem before you get here.
Good Luck,
Bill


Tejas
User

Nov 18, 2014, 10:58 PM

Post #30 of 30 (5893 views)
Re: [Tejas] How to Access all the values of multilevel hash [In reply to] Can't Post

Thanks
Iam trying to acheive this in the code..

First page Previous page 1 2 Next page Last page  View All
 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives