neversaint
neversaint

Reputation: 64064

Printing Hash of Hash into a Matrix Table in Perl

I have a data structure like this:

#!/usr/bin/perl -w
my $hash = {
             'abTcells' => {
                             'mesenteric_lymph_node' => {
                                                         'Itm2a'   => '664.661',
                                                         'Gm16452' => '18.1425',
                                                         'Sergef'  => '142.8205'
                                                       },

                               'spleen'       =>   {  
                                                       'Itm2a' => '58.07155',
                                                       'Dhx9' => '815.2795',
                                                       'Ssu72' => '292.889'

                                                }
                            }
            };

What I want to do is to print it out into this format:

                mesenteric_lymph_node       spleen
Itm2a               664.661                 58.07155
Gm16452             18.1425                 NA
Sergef              142.8205                NA
Dhx9                 NA                     815.2795
Ssu72                NA                     292.889

What's the way to do it.

I'm currently stuck with the following code https://eval.in/44207

foreach my $ct (keys %{$hash}) {
     print "$ct\n\n";
     my %hash2 = %{$hash->{$ct}};
       foreach my $ts (keys %hash2) {
       print "$ts\n";
       my %hash3 = %{$hash2{$ts}};
       foreach my $gn (keys %hash3) {
          print "$gn $hash3{$gn}\n";
       }
     }
 }

Upvotes: 1

Views: 1081

Answers (3)

David W.
David W.

Reputation: 107090

First thing would be to separate out the two hashes:

my %lymph_node =  %{ $hash->{abTcells}->{mesenteric_lymph_node} };
my %spleen     =  %{ $hash->{abTcells}->{spleen} };

Now, you have two separate hashes that contains the data you want.

What we need is a list of all the keys. Let's make a third hash that contains your keys.

my %keys;
map { $keys{$_} = 1; } keys %lymph_node, keys %spleen;

Now, we can go through all your keys and print the value for each of the two hashes. If one of the hashes doesn't have the data, we'll set it to NA:

for my $value ( sort keys %keys ) {
    my $spleen_value;
    my $lymph_nodes_value;
    $spleen_value = exists $spleen{$value} ? $spleen{$value} : "NA";
    $lymph_node_value = exists $lymph_node{$value} ? $lymph_node{$value} : "NA";
    printf "%-20.20s  %-9.5f %-9.5f\n", $key, $lymph_node_value, $spleen_value;
}

The printf statement is a nice way to tabularize data. You'll have to create the headings yourself. The ... ? ... : ... statement is an abbreviated if/then/else If the statement before the ? is true, then the value is the value between the ? and the :. Else, the value is the value after the :.

Upvotes: 1

Sinan Ünür
Sinan Ünür

Reputation: 118166

Use Text::Table for output. Beautify to taste.

#!/usr/bin/env perl

use strict;
use warnings;

use Text::Table;

my $hash = {
    'abTcells' => {
        'mesenteric_lymph_node' => {
            'Itm2a'   => '664.661',
            'Gm16452' => '18.1425',
            'Sergef'  => '142.8205'
        },
        'spleen' =>  {
            'Itm2a' => '58.07155',
            'Dhx9' => '815.2795',
            'Ssu72' => '292.889'
        }
    }
};

my $struct = $hash->{abTcells};

my @cols = sort keys %{ $struct };
my @rows = sort keys %{ { map {
    my $x = $_;
    map { $_ => undef }
    keys %{ $struct->{$x} }
} @cols } };

my $tb = Text::Table->new('', @cols);

for my $r (@rows) {
    $tb->add($r, map $struct->{$_}{$r} // 'NA', @cols);
}

print $tb;

Output:

        mesenteric_lymph_node spleen
Dhx9    NA                    815.2795
Gm16452  18.1425              NA
Itm2a   664.661                58.07155
Sergef  142.8205              NA
Ssu72   NA                    292.889

Now, the order of the rows above is different than the one you show because I wanted it to be consistent. If you know the set of all possible rows, then you can specify another order obviously.

Upvotes: 4

Karthik T
Karthik T

Reputation: 31962

Both of your inner hashes have the same keys, So do a foreach on one of the hashes to get the key, and then print both.

Upvotes: 0

Related Questions