Solved

Simplify hash structure

Posted on 2007-03-20
5
236 Views
Last Modified: 2010-03-05
Hi all,
I need to modify the hash structure given below:
$hash_value = { '75.34.42.17561630730' => { '2005' => [ '11.5', '147,296' ], '2004' => [ '9.2', '132,116' ], '2002' => [ '7.6', '114,837' ], '2000' => [ '', '100,000' ], '2006' => [ '9.4', '161,184' ], '2001' => [ '6.7', '106,733' ], '2003' => [ '5.4', '120,988' ] },
'75.34.42.17510225758' => { '2004' => [ '', '618,000' ], '2002' => [ '7.6', '709,694' ], '2001' => [ '6.7', '659,608' ] } };

The outer hash key for the $hash_value  is '75.34.42.17561630730' and '75.34.42.17510225758' .
which points to set of keys called year (2005 ,2004 etc) and which point to array.

I would like to get the above hash in the form as
$hash_new_before_sort = { '2005' => [ '11.5', '147,296' ,'',''], '2004' => [ '9.2', '132,116' ,'', '618,000' ], '2002' => [ '7.6', '114,837','7.6', '709,694' ], '2000' => [ '', '100,000' ,'',''], '2006' => [ '9.4', '161,184' ,'',''], '2001' => [ '6.7', '106,733' ,'6.7', '659,608' ], '2003' => [ '5.4', '120,988','','' ]}

that's 2nd record set will be added to the 1st set -  (  '75.34.42.17561630730' is the 1st record set and  '75.34.42.17510225758'  2nd record set). If year not present in the 2nd set ,null values ('') will be added to the year array.

and sort keys by ascending
$hash_new_after_sort = { '2000' => [ '', '100,000' ,'',''],  '2001' => [ '6.7', '106,733' ,'6.7', '659,608' ], '2002' => [ '7.6', '114,837','7.6', '709,694' ], '2003' => [ '5.4', '120,988','','' ],'2004' => [ '9.2', '132,116' ,'', '618,000' ], '2005' => [ '11.5', '147,296' ,'',''], '2006' => [ '9.4', '161,184' ,'','']}

Thanks

0
Comment
Question by:r_kar
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 39

Accepted Solution

by:
Adam314 earned 125 total points
ID: 18758307
The order you enter data into the hash is irrelevant.  If you need to process things in a sorted order, you sort it when you are using it, not when you enter it.

use Data::Dumper;

my $hash_value = {
  '75.34.42.17561630730' => {
    '2005' => [ '11.5', '147,296' ],
    '2004' => [ '9.2', '132,116' ],
    '2002' => [ '7.6', '114,837' ],
    '2000' => [ '', '100,000' ],
    '2006' => [ '9.4', '161,184' ],
    '2001' => [ '6.7', '106,733' ],
    '2003' => [ '5.4', '120,988' ] },
  '75.34.42.17510225758' => {
    '2004' => [ '', '618,000' ],
    '2002' => [ '7.6', '709,694' ],
    '2001' => [ '6.7', '659,608' ] } };


#Get all keys for main hash
my @mainkeys=keys %$hash_value;

#Get all years
my %years;
foreach my $mainkey (keys %$hash_value) {
      foreach my $year (keys %{ $hash_value->{$mainkey} } ) {
            $years{$year}=1;
      }
}

my $new_hash;
foreach my $mainkey (keys %$hash_value) {
      foreach my $year (keys %years) {
            if(!exists($hash_value->{$mainkey}->{$year})){
                  #Add empty string if year doesn't exist
                  push @{ $new_hash->{$year} }, '';
                  next;
            }
            push @{ $new_hash->{$year} }, $_ foreach ( @{ $hash_value->{$mainkey}->{$year} } );
      }
}

print Dumper($new_hash);
0
 
LVL 84

Assisted Solution

by:ozo
ozo earned 125 total points
ID: 18758438
use Data::Dumper;
$hash_value = { '75.34.42.17561630730' => { '2005' => [ '11.5', '147,296' ], '2004' => [ '9.2', '132,116' ], '2002' => [ '7.6', '114,837' ], '2000' => [ '', '100,000' ], '2006' => [ '9.4', '161,184' ], '2001' => [ '6.7', '106,733' ], '2003' => [ '5.4', '120,988' ] },
'75.34.42.17510225758' => { '2004' => [ '', '618,000' ], '2002' => [ '7.6', '709,694' ], '2001' => [ '6.7', '659,608' ] } };
my $i;
for( '75.34.42.17561630730', '75.34.42.17510225758' ){
  while( my($k,$v) = each %{$hash_value->{$_}} ){
     @{$hash_new_before_sort->{$k}}[$i,$i+1] = @$v;
  }
  $i += 2;
}
print Dumper $hash_new_before_sort;
# hashes are an unordered data structure, so it doesn't make sense to takl about sorting it
# you can sort a lis of keys and do something with that
$"=", ";
for( sort keys %$hash_new_before_sort ){
   print "$_ => [@{$hash_new_before_sort->{$_}}]\n";
}
# or you could use a module that implements Perl hashes that preserve the order
use Tie::IxHash;
$t = tie(%hash_new_after_sort, Tie::IxHash);
for( sort keys %$hash_new_before_sort ){
    $hash_new_after_sort{$_} = $hash_new_before_sort->{$_};
}
0
 

Author Comment

by:r_kar
ID: 18762044
Hi Adam314,ozo
Thanks a lot for your help.
The blow structure (now it contains 4 records) I used to test the code. There is some problem in output.

my $hash_value = { '75.34.42.17534849371' => { '2005' => [ '11.5', '257,768' ], '2004' => [ '9.2', '231,202' ], '2001' => [ '6.7', '186,782' ], '1998' => [ '', '175,000' ], '2002' => [ '7.6', '200,965' ], '2006' => [ '9.4', '282,072' ], '2000' => [ '7.7', '175,000' ], '2003' => [ '5.4', '211,728' ], '1999' => [ '-42.4', '162,436' ] },
'75.34.42.17561630730' => { '2005' => [ '11.5', '147,296' ], '2004' => [ '9.2', '132,116' ], '2002' => [ '7.6', '114,837' ], '2000' => [ '', '100,000' ], '2006' => [ '9.4', '161,184' ], '2001' => [ '6.7', '106,733' ], '2003' => [ '5.4', '120,988' ] },
'75.34.42.17511726663' => { '2005' => [ '11.5', '294,592' ], '1995' => [ '', '200,000' ], '2004' => [ '9.2', '264,231' ], '2001' => [ '6.7', '213,465' ], '2002' => [ '7.6', '229,675' ], '2006' => [ '9.4', '322,368' ], '2000' => [ '7.7', '200,000' ], '2003' => [ '5.4', '241,975' ], '1999' => [ '-42.4', '185,641' ] },
'75.34.42.17510225758' => { '2004' => [ '', '618,000' ], '2002' => [ '7.6', '709,694' ], '2001' => [ '6.7', '659,608' ] } };

adam314,
provided code is excellent. I have added '' in push @{ $new_hash->{$year} }, '',''; to maintain the structure.
The problem which I noticed, I won't be able to distinguish the array values that belongs to outer key )say '75.34.42.17534849371'  etc). The above structure contains 4 outer keys ('75.34.42.17534849371','75.34.42.17561630730', '75.34.42.17561630730','75.34.42.17511726663','75.34.42.17510225758'). So we can say first 2 data in the array belongs to '75.34.42.17534849371' and next 2 data belongs to '75.34.42.17561630730' etc. But in ozo's code I can distinguish (there is some problem with some year data).
Could you please help me to resolve those issue?

ozo,
different approach and its excellent. I got lots of ideas from you and adam314.
There is some problem in year 2000, Actually we need to display
2000 => [ 7.7, 175,000, , 100,000, 7.7,  200,000, , , ]
But from present output, its displaying
2000 => [ 7.7, 175,000, , 100,000,  , 100,000,  7.7,  200,000 ] # additional value ( , 100,000) can be seen

same thing happend in 2006 also.

Could you please resolve this?

Thanks
0
 
LVL 84

Expert Comment

by:ozo
ID: 18762306
I think , 100,000, is appearing twice because
75.34.42.17561630730 is listed twice in your list
('75.34.42.17534849371','75.34.42.17561630730', '75.34.42.17561630730','75.34.42.17511726663','75.34.42.17510225758')
If the purpose of having 75.34.42.17561630730 twice was not to have , 100,000, twice, then how did you get 7.7, 175,000, , 100,000, 7.7,  200,000, , , ]?

Will the first outer key listed always contain all the inner keys that will be found within subsequent inner keys?
0
 

Author Comment

by:r_kar
ID: 18787411
Hi Adam314, ozo,

I have modified the script as per my requirement. Thanks  a lot for your help.
0

Featured Post

Enroll in June's Course of the Month

June’s Course of the Month is now available! Experts Exchange’s Premium Members, Team Accounts, and Qualified Experts have access to a complimentary course each month as part of their membership—an extra way to sharpen your skills and increase training.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

729 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question