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


Tejas
User

Nov 14, 2014, 4:48 AM

Post #1 of 30 (12043 views)
How to Access all the values of multilevel hash Can't Post


Code
use strict; 
use warnings;


my $etid_mapping_file = $ARGV[0];
open etid_mapping_file, "< $etid_mapping_file" or die "could not open first file..\n";
my %etid_mapping_hash;


while (my $etid_line = <etid_mapping_file>)
{
chomp($etid_line);
my ($co,$automated_or_manual,$sl_source,$source,$description,$etid1) = split '\|', $etid_line;
if ($etid1)
{
push @{$etid_mapping_hash{$co}{$automated_or_manual}{$sl_source}{$source}{$description}{Entry}},$etid1;
}
else
{
$etid_mapping_hash{$co}{$automated_or_manual}{$sl_source}{$source}{$description}="TBD";
}
}


Input File

Quote

04|Automated|LSE|GOAN|Retail Sales|1
04|Automated|LSE|GOAN|Retail Sales (none)|47
04|Automated|LSE|GOAN| Sales|204
04|Automated|LSE|GOAN| Sales|526
04|Automated|LSE|GOAN| Sales|68
04|Automated|LSE|GOAN| Sales|69
04|Automated|LSE|GOAN|Magazine Sales (none)|52
04|Automated|LSE|GOAN|Magazine Sales|13
04|Automated|LSE|CReturns|Retail Retrocharge Instant Refund|9
04|Automated|LSE|GOAN|Retail Exchange Sales|12
04|Automated|LSE|CReturns| Free|32
04|Automated|LSE|MOON|Shipment|234
04|Automated|finc|Revenue|CORNTAB Revenue|12
2R|Automated|LSE|GOAN|MyHabit Sales|526
2R|Automated|LSE|GOAN|Small Parts Sales|1
04|Automated|LSE|PIEGION| Refund|700
04|Automated|LSE|PIEGION| Refund|701
04|Automated|LSE|CReturns|Retrocharge|523
2R|Automated|LSE|PIEGION|Retail Refund|700
2R|Automated|LSE|PIEGION|Refund|701
79|Automated|LSE|PIEGION|Retail Refund|700
06|Automated|LSE|PIEGION|Retail Refund|701


As u can see for some lines all the kes are same except the final key,so i had to use array

Im stcuk at how this has to printed individually.

Also , how to know which hash has the grouped values (1-2-3)
and which have individual value (1).

Also, Im not clear about ungrouping them
ex: if i have 1-2-3
how to get the individual values from this array

When i split the array using "-" which i used while joining


split '-',$ETID;

This is the error i get

Use of implicit split to @_ is deprecated at ./Entry_Type_Hash.pl line 43.
Hope iam clear
Thanks
Tejas


(This post was edited by Tejas on Nov 14, 2014, 5:50 AM)


Tejas
User

Nov 14, 2014, 8:39 AM

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

Guess no oen has looked into it :)


FishMonger
Veteran / Moderator

Nov 14, 2014, 9:34 AM

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

I don't understand what you're asking.

Your references to the 1-2-3 values doesn't make mush sense especially since there's nothing in either your source data or your code to give any clue where that comes from.


Quote
Use of implicit split to @_ is deprecated

That error is telling you that you're trying to use an array as the string expression, which is wrong. The split function work on a single string not an array.

Please post a short but complete script that demonstrates the problem and rephrase your question so that we can understand what you're needing.


(This post was edited by FishMonger on Nov 14, 2014, 9:36 AM)


Tejas
User

Nov 14, 2014, 9:42 AM

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


Quote
I have stored data from a fileinto a hash using below


Code
while (my $etid_line = <etid_mapping_file>) 
{
chomp($etid_line);
my ($co,$automated_or_manual,$sl_source,$source,$description,$etid1) = split '\|', $etid_line;
if ($etid1)
{
push @{$etid_mapping_hash{$co}{$automated_or_manual}{$sl_source}{$source}{$description}{Entry}},$etid1;
}
else
{
push @{$etid_mapping_hash{$co}{$automated_or_manual}{$sl_source}{$source}{$description}{Entry}},"TBD";
}



}


There's is one more hash which is being created using another input file

Code
while (my $gl_line = <gl_file>) 
{
chomp($gl_line);
my ($_company_code,$gl_account_number,$_project_code,$_account_name,$accounting_document_source,$journal_category,$accounting_document_name,$line_desc,$effective_date,$fiscal_period,$user_login,$transaction_document_amount,$ledger_name,$subledger_source,$source_system,$automated_manual,$categorized,$etid_mapping) =split '\|', $gl_line;
$gl_hash{$_company_code}{$automated_manual}{$subledger_source}{$source_system}{$categorized}=
(defined $gl_hash{$_company_code}{$automated_manual}{$subledger_source}{$source_system}{$categorized} ?
$gl_hash{$_company_code}{$automated_manual}{$subledger_source}{$source_system}{$categorized}:0) + $transaction_document_amount;

}



And iam trying to read some the data in gl_hash in $etid_mapping_hash{ just to see whether the mapping exists or not
and it s just become impossible for me to retrive or chck the values


Code
 
# i have number of hashes that use below code, so have to send a paramater

print_txn_wise_hash("Some Type",\%gl_hash) ;



sub print_txn_wise_hash
{
my $txn_type =shift;
my $gl_hash = shift;
my ($automated_manual,$subledger_source,$source_system,$categorized,$gl_amount);
my ($company_codes,$automated_manuals,$subledger_sources,$source_systems,$categorizeds);
my ($etid,$desc,$sl_amount,$diff);

while (($company_codes, $automated_manuals) = each %$gl_hash)
{
while (($automated_manual, $subledger_sources) = each %$automated_manuals)
{
while (($subledger_source, $source_systems) = each %$subledger_sources)
{
while (($source_system, $categorizeds) = each %$source_systems)
{
while (($categorized, $gl_amount) = each %$categorizeds)
{
my $etid_group = join('-', @{$etid_mapping_hash{$_company_codes}{$automated_manual}{$subledger_source}{$source_system}{$categorized}{$gl_amount}{Entry} } );
my @items = split(/-/, $etid_group );
my $num_of_item = @items;
print "etid_group => $num_of_item \n";
if($num_of_item < 1) {
$etid = "TBD";}
for my $i (0..$#items) {
print "$_company_codes|$automated_manual|$subledger_source|$source_system|$categorized|$gl_amount\n";
}
}
}
}
}
}
}




If iam comennting the lines below,everything seems to be perfect.

Code
# my $etid_group = join('-', @{$etid_mapping_hash{$_company_codes}{$automated_manual}{$subledger_source}{$source_system}{$categorized}{$gl_amount}{Entry} } ); 
# my @items = split(/-/, $etid_group );
# my $num_of_item = @items;
# print "etid_group => $num_of_item \n";
# if($num_of_item < 1) {
# $etid = "TBD";}
# for my $i (0..$#items) {


Quote
Ive been on this for 8 hours now nad dint find the mistake,
Is it clear now ?


Thanks
Tejas


FishMonger
Veteran / Moderator

Nov 14, 2014, 9:52 AM

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

Your code formatting is horrible which makes reading/following your code difficult.


Quote
Is it clear now ?

No, not really but I'll look it over.

It would be helpful if you would do as I asked i.e., post a short but complete script that demonstrates the problem so that I can run some tests.


(This post was edited by FishMonger on Nov 14, 2014, 9:52 AM)


Laurent_R
Veteran / Moderator

Nov 14, 2014, 10:48 AM

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


In Reply To
When i split the array using "-" which i used while joining

split '-',$ETID;

This is the error i get

Use of implicit split to @_ is deprecated at ./Entry_Type_Hash.pl line 43.


This happens when you don't split into an array (or into a list).

The correct syntax is:


Code
my @some_array = split /-/, $ETID; 
# or:
my ($this, $that, $this_thing, $another_thing) = split /-/, $ETID;


(BTW, split uses a regular expression for the splitting pattern, not a string as you do several times in your script.)

If you do this:

Code
split  /-/, $ETID;

you are using a very old Perl syntax that would put the result of split into the default @_ array. This syntax is now deprecated because (among other reasons), you might clobber the @_ array and lose the arguments passed to the subroutine.

This is the meaning of the warning you received. This syntax has not been removed to preserve compatibility of very old programs, but you should not use it anymore. Always split into an array or a list.

For your other questions, I don't really understand what you are trying to do, or what exactly you don't succeed to do.


Tejas
User

Nov 14, 2014, 11:30 AM

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

Sorry for that

But i would make it short and try to explain

i have set of lines in a file, which iam storing in a hash

etid_mapping_file:

Quote
04|Automated|SATE|GCS|Redemption|18
04|Automated|SATE|GCS|Redemption|22
04|Automated|SATE|GCS|Redemption|18
04|Automated|SATE|GCS|Return-for-Return|25
04|Automated|SATE|GCS|Return-to-Purchaser|24
04|Automated|SATE|GCS|Return-to-Recipient|46

Code for storing above hash is below
Iam storing it in an array as i have set of same keys with different final values

Code
while (my $etid_line = <etid_mapping_file>) 
{
chomp($etid_line);
my ($co,$automated_or_manual,$sl_source,$source,$description,$etid1) = split '\|', $etid_line;
if ($etid1)
{
push @{$etid_mapping_hash{$co}{$automated_or_manual}{$sl_source}{$source}{$description}{Entry}},$etid1;
}
else
{
push @{$etid_mapping_hash{$co}{$automated_or_manual}{$sl_source}{$source}{$description}{Entry}},"TBD";
}
}


Now I have another hash will iam filling using another input file.

gl_file :

Quote
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement



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;
$gl_hash{$_company_code}{$automated_manual}{$subledger_source}{$source_system}{$categorized} += $transaction_document_amount;

}



Now We have two hashes (One is Hash of array and other is a hash)

Finally, Iam Trying to search the keys and values of gl_hash in $etid_mapping_hash

and there might be more than one output

For Traversing the hash , below is the code,
Im going thorugh each of the keys and values searching it in another hash,where iam facing trouble

I am trying to get the data from gl_hash
and search the same in etid_maping_hash and i might get a list of values here. and print them


Code
 
while (($company_codes, $automated_manuals) = each %$gl_hash)
{
while (($automated_manual, $subledger_sources) = each %$automated_manuals)
{
while (($subledger_source, $source_systems) = each %$subledger_sources)
{
while (($source_system, $categorizeds) = each %$source_systems)
{
while (($categorized, $gl_amount) = each %$categorizeds)
{
my $etid_group = join('-', @{$etid_mapping_hash{$_company_codes}{$automated_manual}{$subledger_source}{$source_system}{$categorized}{$gl_amount}{Entry} } );
my @items = split(/-/, $etid_group );
my $num_of_item = @items;
print "etid_group => $num_of_item \n";
if($num_of_item < 1) {
$etid = "TBD";}
for my $i (0..$#items) {
print "$_company_codes|$automated_manual|$subledger_source|$source_system|$categorized|$gl_amount\n";
}
}
}
}
}
}
}




Quote

If it is still not clearer
I can say that
I am getting the values from multi level hash
and searching it in another multi level hash (Array of hashes)

my %first ;
$first{one}{two} = three;

my %second ;
$second{one}{two} = four; //With same keys as above the value is Four

And iam trying to fetch the values from second hash ,
Just that in my original code i have set of diferent values for same keys.so iam using array of hashes...And want to print all the values i n that array

Is it Clearer ?

Thanks
Tejas


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


Tejas
User

Nov 14, 2014, 7:07 PM

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

did u get a chance to look at this latest update


Laurent_R
Veteran / Moderator

Nov 15, 2014, 7:25 AM

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

Well, I have no time right now to test or study your code in details. But a couple of brief comments.


I do not think that using a nested hash is the best for your second data set (the general ledger), because it makes retrieving the data fairly complex, with these nested while loops.

A flat hash might make things easier:

Code
my ($_company_code,$transaction_document_amount,$subledger_source,$source_system,$automated_manual,$categorized) =split /| /, $gl_line;   
$gl_hash{"$_company_code-$automated_manual-$subledger_source-$source_system-$categorized} += $transaction_document_amount;


Then you can have something like this:

Code
foreach my $key (keys %gl_hash) { 
my ($cc, $am, $sub, $source, $cat) = split /-/, $gl_hash{$key};
# proceed with look up into the other hash
}

This is untested, but I think that you can at least get the idea.

Second point: assuming everything worked correctly in the first phase, you don't have an array of hashes, but a hash of hashes of hashes ... of arrays.

Third: why do you join the content of your array just to split it in the next instruction in your last chunk of code?

In your code,

Code
$etid_mapping_hash{$_company_codes}{$automated_manual}{$subledger_source}{$source_system}{$categorized}{$gl_amount}{Entry}

if it exists, is a reference to an array. So you could just have something like this:

Code
my @items = @{ $etid_mapping_hash{$_company_codes}{$automated_manual}{$subledger_source}{$source_system}{$categorized}{$gl_amount}{Entry} };


One final point: from looking at your nested while loops, it seems that you are not using :

Code
use strict; 
use warnings;

You should really do it all the time, but even more when you deal with complicated data structures where you can easily make mistakes on many things, including simple variables names.

The final point is that you should tell us in which respect your code does not work. Does it compile or not? Do you have warnings or errors? Which errors, if any? At compile time or at run time? Or does it simply not do what you expect? That would really help us to help you.


FishMonger
Veteran / Moderator

Nov 15, 2014, 7:53 AM

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

I had some of the same thoughts as Laurent_R and was going to post those thoughts in detail but will hold off.

I will post 2 short test scripts that demonstrate a cleaner and simpler way to build the hashes (i.e., flatten them).


Code
#!/usr/bin/perl 

use strict;
use warnings;
use Data::Dumper;

my %etid_mapping_hash;

while (my $etid_line = <DATA>) {
chomp $etid_line;
my @fields = split /\|/, $etid_line, 6;
my $etid1 = pop @fields;
$etid1 = $etid1 ? $etid1 : 'TBD';
my $key = join '|', @fields;
push @{ $etid_mapping_hash{$key} }, $etid1;
}
#print Dumper \%etid_mapping_hash;

foreach my $key (sort keys %etid_mapping_hash) {
print "$key => $_\n" for @{ $etid_mapping_hash{$key} };
}

__DATA__
04|Automated|SATE|GCS|Redemption|18
04|Automated|SATE|GCS|Redemption|22
04|Automated|SATE|GCS|Redemption|
04|Automated|SATE|GCS|Return-for-Return|25
04|Automated|SATE|GCS|Return-to-Purchaser|24
04|Automated|SATE|GCS|Return-to-Recipient|46

Oututs:

Quote
04|Automated|SATE|GCS|Redemption => 18
04|Automated|SATE|GCS|Redemption => 22
04|Automated|SATE|GCS|Redemption => TBD
04|Automated|SATE|GCS|Return-for-Return => 25
04|Automated|SATE|GCS|Return-to-Purchaser => 24
04|Automated|SATE|GCS|Return-to-Recipient => 46



Code
#!/usr/bin/perl 

use strict;
use warnings;
use Data::Dumper;

my %gl_hash;

while (my $gl_line = <DATA>) {
chomp $gl_line;
my @fields = split /\|/, $gl_line;
my $key = join '|', @fields[0,4,2,3,5];
my $value = $fields[1];
$gl_hash{$key} += $value;
}
print Dumper \%gl_hash;


__DATA__
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement
04|45.90|SATE|GCS|Automated|Settlement


Outputs:

Code
$VAR1 = { 
'04|Automated|SATE|GCS|Settlement' => '229.5'
};


EDIT:
If you enable the "print Dumper" statement in the first script you'll get this additional output:

Code
$VAR1 = { 
'04|Automated|SATE|GCS|Return-to-Purchaser' => [
'24'
],
'04|Automated|SATE|GCS|Redemption' => [
'18',
'22',
'TBD'
],
'04|Automated|SATE|GCS|Return-to-Recipient' => [
'46'
],
'04|Automated|SATE|GCS|Return-for-Return' => [
'25'
]



(This post was edited by FishMonger on Nov 15, 2014, 8:22 AM)


FishMonger
Veteran / Moderator

Nov 15, 2014, 8:33 AM

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

If you want to use individual scalars (to be self documenting) instead of the @fields array I used, then please add vertical whitespace to make it readable.


Code
my ($_company_code, 
$transaction_document_amount,
$subledger_source,
$source_system,
$automated_manual,
$categorized)
= split /\|/, $gl_line;



BillKSmith
Veteran

Nov 15, 2014, 9:52 AM

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

Your variable $catagorized always contains the string 'Settlement'. This is not a key of any sub-hash of %etid_mapping_hash. When you try to use it as a key, a new key is created. This clearly does not make sense, but I do not know what you intend.
Good Luck,
Bill


Laurent_R
Veteran / Moderator

Nov 15, 2014, 10:39 AM

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

I also noticed that, but concluded that we were just looking at two different (and not intersecting) subsets of the real data, and that the value of that field could be either "Redemption", "Settlement", "Return...", etc. Of course, if it is not the case, it's not gonna work.


Tejas
User

Nov 15, 2014, 10:56 PM

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

If that is the case, should I use defined keywprd


Tejas
User

Nov 15, 2014, 11:00 PM

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

Can u please elaborate exactly
If I am searching for something not available , it generates anew key and what happens next ?
Can u please elaborate ?


Laurent_R
Veteran / Moderator

Nov 16, 2014, 6:42 AM

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

Hi Tejas,

The problem is that the data in the second file does not match the data in the first file.


Tejas
User

Nov 16, 2014, 7:42 AM

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

And if it doesn't match , it creates a new hash key

What could be the potential issues with this?


Laurent_R
Veteran / Moderator

Nov 16, 2014, 9:26 AM

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

There is process called autovivification, which works like this (session under the Perl debugger):


Code
  DB<1> %hash = (); # create empty hash 

DB<2> print "true" if exists $hash{a}{b}{c}{d};

DB<3> x \%hash;
0 HASH(0x600500b60)
'a' => HASH(0x600500bf0)
'b' => HASH(0x6005009e0)
'c' => HASH(0x600500968)
empty hash

I created an empty hash %hash, then checked if the value $hash{a}{b}{c}{d} existed. This alone created the nested keys a, b and c (all keys except the last one).

This is also what will happen in your etid hash if you look for a non-existent deeply nested value: the intermediate keys (all except the last one) will autovivify if they don't already exist. This may or may not be a problem depending on how you use the hash after. If you always look for a fifth-level nested value, you may not care too much about creating new keys down to the 4th level. But there are cases where it makes a difference, especially when you look for data at various degrees of nestedness. This is not what you are doing in your code, so it should not matter too much in your case.

One thing is sure, though: if you use flat hashes as shown by FishMonger and myself in previous posts (posts #9 and #10, that you don't seem to have noticed, you should really go back and read them), there will be no autovivification at all and you are 100% sure of not running into this type of trouble.

But the real problem pointed out by Bill is that the data samples you have shown will never match with each other since the category is always "setlement" in the GL file and this category is never there in the other file. And that's really what Bill was concerned about, the data you've shown does not really make sense, since it will never match; the issue of that possibly creating intermediate hash levels was only secundary collateral effect.


BillKSmith
Veteran

Nov 16, 2014, 8:17 PM

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

Laurent has already explained the real problem very well. Actually your code aborts sooner than I expected. You must understand autovivification in order to understand the error message.


Using the data from your post #7, when you try to reference the hash %setid_mapping_hash for the first time, this is the situation:


Code
use strict; 
use warnings;
use Data::Dumper qw(Dumper);
$Data::Dumper::Indent = 1;
my %setid_mapping_hash = (
'04' => {
'Automated' => {
'SATE' => {
'GCS' => {
'Return-to-Recipient' => {
'Entry' => [
'46'
]
},
'Redemption' => {
'Entry' => [
'18',
'22',
'18'
]
},
'Return-for-Return' => {
'Entry' => [
'25'
]
},
'Return-to-Purchaser' => {
'Entry' => [
'24'
]
}
}
}
}
}
);

my $_company_codes = 4;
my $automated_manual = 'Automated';
my $subledger_source = 'SATE';
my $source_system = 'GCS';
my $categorized = 'Settlement';
my $gl_amount = 229.5;

my $setid_group = join('-', @{
$setid_mapping_hash
{$_company_codes}
{$automated_manual}
{$subledger_source}
{$source_system}
{$categorized}
{$gl_amount}
{Entry}
} );


When the last statement executes, the program dies with the following message:

Code
Can't use an undefined value as an ARRAY reference at C:\Documents and Settings\ 
bill\Perl\guru\tejas_13.pl line 46.


In order to understand this, replace the ofending statement with this and run again

Code
my $temp_ref = $setid_mapping_hash 
{$_company_codes}
{$automated_manual}
{$subledger_source}
{$source_system}
{$categorized}
{$gl_amount}
{Entry}
;
print Dumper( \%setid_mapping_hash, \$temp_ref);
my $setid_group = join '-', @$temp_ref;


Now, the output is:

Code
$VAR1 = { 
'4' => {
'Automated' => {
'SATE' => {
'GCS' => {
'Settlement' => {
'229.5' => {}
}
}
}
}
},
'04' => {
'Automated' => {
'SATE' => {
'GCS' => {
'Return-to-Recipient' => {
'Entry' => [
'46'
]
},
'Redemption' => {
'Entry' => [
'18',
'22',
'18'
]
},
'Return-to-Purchaser' => {
'Entry' => [
'24'
]
},
'Return-for-Return' => {
'Entry' => [
'25'
]
}
}
}
}
}
};
$VAR2 = \undef;
Can't use an undefined value as an ARRAY
bill\Perl\guru\tejas_13.pl line 55.


Now you can see how the original hash is changed and $temp_ref is undefined. Note that the original code is the same except that $temp_ref is anonymous.

It is not easy to test for this type of error without changing the original hash (which might mask other errors). Even if you could, what would you do? You probably want the program to die so you fix the data.
Good Luck,
Bill


Tejas
User

Nov 17, 2014, 5:43 AM

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

Thanks You for the inputs,i have written the code the way whefre i just have a single key .
And that worked
As i have to write everything to an excel sheet, I have written code identical to below lines


Code
if (defined @{ $etid_mapping_hash{$key} } ) { }//Write to Excl sheet 
my @etid_list = @{ $etid_mapping_hash{$key} } ;
for my $i (0..$#etid_list) {
$GL_SL->write($row_count, 8, $vp_id,$cell_frmt);
$GL_SL->write_string($row_count, 9, $_company_code,$cell_center_frmt);
$GL_SL->write($row_count, 10, $subledger_source,$cell_frmt);
$GL_SL->write($row_count, 11, $etid,$cell_frmt);
$GL_SL->write($row_count, 12, $desc,$cell_frmt);
$GL_SL->write($row_count, 13, $sl_amount,$amount_format);
}
if( not defined @{ $etid_mapping_hash{$key} } ) { //Write empty rows to excel sheet}

Without this its throwing


Quote
There are some global variables which ia writing to excel like vpcl_id etc


Now i also have something below to make things easier.
I have created around 300 hashes and set their values to true

$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"nanakde"}{"Pure"}= 1 ;
$settle_hash{"04"}{"nanakde"}{"Pure"}= 1 ;
$settle_hash{"04"}{"nanakde"}{"Pure"}= 1 ;
$settle_hash{"04"}{"nanakde"}{"Pure"}= 1 ;
$settle_hash{"04"}{"nanakde"}{"Jagap"}= 1 ;
$settle_hash{"04"}{"nanakde"}{"Jagap"}= 1 ;
$settle_hash{"04"}{"nanakde"}{"Jagap"}= 1 ;
$settle_hash{"3S"}{"nanakde"}{"Jagap"}= 1 ;
$settle_hash{"06"}{"nanakde"}{"Jagap"}= 1 ;
$settle_hash{"79"}{"Janek"}{"Jagap"}= 1 ;
$settle_hash{"2R"}{"Janek"}{"Jagap"}= 1 ;
$settle_hash{"04"}{"Janek"}{"narek"}= 1 ;
$settle_hash{"04"}{"Janek"}{"narek"}= 1 ;
$settle_hash{"04"}{"Janek"}{"narek"}= 1 ;
$settle_hash{"04"}{"Janek"}{"meher"}= 1 ;
$settle_hash{"04"}{"Janek"}{"meher"}= 1 ;
$settle_hash{"04"}{"Janek"}{"meher"}= 1 ;
$settle_hash{"04"}{"Janek"}{"meher"}= 1 ;
$settle_hash{"04"}{"Janek"}{"meher"}= 1 ;
$settle_hash{"04"}{"Janek"}{"meher"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;
$settle_hash{"04"}{"Janek"}{"shanu"}= 1 ;

Code
 
And while checking fro the input file


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;
}
}

}


I see whether this hash exist and if it exists in declaration.i end up creating another hash.

Is there a way that i can skip this hash creation, and any other suggestions ?

And is there a way that i can write all these hashes in a seperate file and use it in this file
Or Is there a way that i can entirely skip creating these boolean hashes
Thanks
Tejas


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


BillKSmith
Veteran

Nov 17, 2014, 8:09 AM

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

Your test for what to write to Excel still has the same problem as before.

The following code contains an examble of each condition that you could encounter and a test for it. Uncomment one of the definitions of $key to demonstrate that the corresponding condition is handled correctly.

Note that the order of the tests is important. Errors are found before autovivification occurs


Code
use strict; 
use warnings;
my %etid_mapping_hash = (
data => [1,2,3],
no_data => [],
non_array => 17,
not_defined => undef,
);
#if (defined @{ $etid_mapping_hash{$key} } ) { #Write to Excl sheet }
#my $key = 'something_else';
#my $key = 'not_defined';
#my $key = 'non_array';
#my $key = 'data';
#my $key = 'no_data';

if (!exists $etid_mapping_hash{$key}) {
die "Invalid data\n";
}
if (!defined $etid_mapping_hash{$key}
or ref $etid_mapping_hash{$key} ne 'ARRAY'
){
die "Error in code which reads mapping file.";
}
if ( @{$etid_mapping_hash{$key}} ) {
print "Write data to Excel\n";
}
else {
print "Write empty row to Excel\n";
}

Good Luck,
Bill


Tejas
User

Nov 17, 2014, 8:25 AM

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

Thanks bill
Here iam required to write the empty rows to excel if it is not defined .
And you suggest me not to use defined or not defined

I will check your code right away.

Thanks
Tejas


Tejas
User

Nov 17, 2014, 8:57 AM

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


Code
use strict;  
use warnings;
my %etid_mapping_hash = (
data => [1,2,3],
no_data => [],
non_array => 17,
not_defined => undef,
);
#if (defined @{ $etid_mapping_hash{$key} } ) { #Write to Excl sheet }
#my $key = 'something_else';
#my $key = 'not_defined';
#my $key = 'non_array';
#my $key = 'data';
my $key = 'no_data';

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'
){
die "Error in code which reads mapping file.";
}
#Are below two statememt's correct in my code.?

if ( @{$etid_mapping_hash{$key}} ) {
print "Write data to Excel\n"; # Only If its an array it prints
}
else {
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
}

Can u please read the comments
And suggest me what has to used in my code.
i think there is no way except unsing not defined for the keys whch dont really exist in the ehash or not exist is also equally fine.
But iam confused more on what to use ?
As there are cases where the key is nt available in my hash at all
and i think both !define and !exists work well,and defined and exist keyword has autovivificvation ?

Also can u comment on the numerous hashes that iam setting to 1.
Is there a way out?


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


FishMonger
Veteran / Moderator

Nov 17, 2014, 9:27 AM

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


Quote
I have created around 300 hashes and set their values to true

Code
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ; 
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;
...
...


Are you saying that those 12 assignments are 12 hashes?

That's 1 hash where you assign the same value to the same hash key 12 times, which makes absolutely no sense.

I edited your post #23 to add the missing code tags and now I see that you've removed those code tags. DO NOT DO THAT!! Never post code without enclosing it in the code tags.


(This post was edited by FishMonger on Nov 17, 2014, 9:28 AM)


Tejas
User

Nov 17, 2014, 9:39 AM

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

sorrt that 's not the case.
I have different keys for all the llines

Code
$settle_hash{"04"}{"Spreadsheet"}{"Pure"}= 1 ;  
$settle_hash{"04"}{"Spreadsheet"}{"APure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"BPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"CPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"DPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"EPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"FPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"GPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"HPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"JADPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"DAGPure"}= 1 ;
$settle_hash{"04"}{"Spreadsheet"}{"WHOPure"}= 1 ;


But the value for all of the keys for this hash is 1 and this is for the condition check..Like below

Code
if($settle_hash{$key1}{$key2}{$key3}) 
{
print "...."
}


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