Solved

Simplify hash structure

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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
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…

733 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