Solved

Simplify hash structure

Posted on 2007-03-20
5
209 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
  • 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
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…
Both in life and business – not all partnerships are created equal. As the demand for cloud services increases, so do the number of self-proclaimed cloud partners. Asking the right questions up front in the partnership, will enable both parties …

863 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

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now