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
Solved

Simplify hash structure

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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

Suggested Solutions

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…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
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…

828 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