EA00
EA00

Reputation: 633

Perl: Nested Hash

I'm trying to write a script to produce a nested hash. My first key/value pair consists of two identifiers - each type of main identifier in the 4th column has a corresponding identifier in 3rd column (can be of variable length), and an associated numeric value in the 6th column.

I was thinking of constructing a key value pair for the identifiers and then sorting the keys (A, B, C, etc.) before incorporating the numerical identifier in a second hash.

Input File

CATE      1  CA   A     1       108.8
CATE      2  CB   A     1       8.33
CATE      3  CA   B     1       45.1
CATE      4  CB   B     1       3.96
CATE      5  CG   B     1       3.94
CATE      6  CA   C     1       1.96
CATE      7  CB   C     1       2.94

Below is my script - when I run it, I don't get any output, and I'm uncertain as to why.

Input Script

#!/usr/bin/perl

use strict;
use warnings;

my $key;
my $value;
my %hash;
my @fields;

my $filename = 'data.txt';
open my $fh, '<', $filename or die "Can't open $filename:$!";

while(my $line = <$fh>) {
    chomp $line;
    @fields = split /\s+/, $line;
    $key = $fields[3];
    $value = $fields[2];
    $hash{$key} = $value;
}

foreach my $name (sort keys %hash) {
    foreach my $type (keys %{ $hash{$fields[5]}}) {
        print "$name, $type: $hash{$name}{$type}\n";
    }
}

Expected Hash structure

A     CA     108.8
      CB     8.33
B     CA     45.1
      CB     3.96
      CG     3.94
C     CA     1.96
      CB     2.94

Upvotes: 0

Views: 153

Answers (2)

Manas Tiwari
Manas Tiwari

Reputation: 11

        #!/usr/bin/perl -w
        use strict;
        use warnings;
        use Data::Dumper;
        open(DATA, "<test.txt") ;
        open(DATA1, ">>test.txt") ;

        while(<DATA>){
            my $data=$_;
            $data=~s/\s+/ /ig;
           my @arr= split(' ',$data);
           my $data1 .= "$arr[3]  $arr[2] $arr[5] \n";
           #print STDERR Dumper($data1);
           print DATA1 $data1;
        }
        close(DATA);
        close(DATA1);

Upvotes: 1

Chris Charley
Chris Charley

Reputation: 6633

Is this what you want?

#!/usr/bin/perl
use strict;
use warnings;

open my $fh, '<', \<<EOF;
CATE      1  CA   A     1       108.8
CATE      2  CB   A     1       8.33
CATE      3  CA   B     1       45.1
CATE      4  CB   B     1       3.96
CATE      5  CG   B     1       3.94
CATE      6  CA   C     1       1.96
CATE      7  CB   C     1       2.94
EOF

my %data;

while (<$fh>) {
    my ($key1, $key2, $val) = (split)[3,2, 5];
    $data{$key1}{$key2} = $val;
}

#use Data::Dumper; print Dumper \%data;

for my $name (sort keys %data) {
    my $href = $data{$name};
    for my $type (sort keys %$href) {
        print "$name, $type, $href->{$type}\n"; 
    }   
}

Output

A, CA, 108.8
A, CB, 8.33
B, CA, 45.1
B, CB, 3.96
B, CG, 3.94
C, CA, 1.96
C, CB, 2.94

Upvotes: 1

Related Questions