简体   繁体   中英

Sorting internal keys hashes of hashes Perl

I am trying to sort a nested hash based on numerical keys. In the code below the $keys(level one) gets sorted easily, I am trying to find an answer on sorting $position (second level) of my hash. Please refer the Data::Dumper snippet below. Let me know if the question needs more clarification.
Thanks

my @array=();
foreach my $keys(sort({ $a <=> $b }keys %process)){
  foreach my $position(sort({ $a <=> $b } keys %{$process{$keys}})){
    foreach my $reference(keys %{$process{$keys}{$position}}){
     my %min=();
     my @arr1=();
     while(my($allele,$frequency)=each %{$process{$keys}{$position}{$reference}}){
        push(@arr1, "$keys\t$position\t$reference\t$allele\treference_val\t$frequency\n");
        $min{1-$frequency}=1;
     }
     my $ref_min=(sort{$min{$b} <=> $min{$a}} keys %min)[0];
     s/reference_val/$ref_min/g for @arr1;
     push(@array,@arr1);
    }
  }
}
foreach(@array){
 chomp;
 print OUT $_,"\n";
}

Data::Dumper

 $VAR1 = '1';
 $VAR2 = {
      '16977' => {
                   'G' => {
                            'A' => '0.0310014'
                          }
                 },
      '77089' => {
                   'C' => {
                            'T' => '0.0171221'
                          }
                 },
      '66442' => {
                   'T' => {
                            'A' => '0.0017295'
                          }
                 },

Expected output:

1  16977 G A 0.0310014
1  66442 C T 0.0171221
1  77089 T A 0.001

It appears to me that you are iterating through the second level of hash in sorted order. I run your code (modified only to go to STDOUT):

use strict;
use warnings;

my %process = (
    '1' => {
      '16977' => {
                   'G' => {
                            'A' => '0.0310014'
                          }
                 },
      '77089' => {
                   'C' => {
                            'T' => '0.0171221'
                          }
                 },
      '66442' => {
                   'T' => {
                            'A' => '0.0017295'
                          }
                 },
    },
);

my @array=();
foreach my $keys(sort({ $a <=> $b }keys %process)){
  foreach my $position(sort({ $a <=> $b } keys %{$process{$keys}})){
    foreach my $reference(keys %{$process{$keys}{$position}}){
     my %min=();
     my @arr1=();
     while(my($allele,$frequency)=each %{$process{$keys}{$position}{$reference}}){
        push(@arr1, "$keys\t$position\t$reference\t$allele\treference_val\t$frequency\n");
        $min{1-$frequency}=1;
     }
     my $ref_min=(sort{$min{$b} <=> $min{$a}} keys %min)[0];
     s/reference_val/$ref_min/g for @arr1;
     push(@array,@arr1);
    }
  }
}
foreach(@array){
 chomp;
 print STDOUT $_,"\n";
}

And get this output:

1   16977   G   A   0.9689986   0.0310014
1   66442   T   A   0.9982705   0.0017295
1   77089   C   T   0.9828779   0.0171221

which differs from your expected output in that it includes the $ref_min value and it has the columns after the first two in a different order (because they were sorted based on position). What do you want to behave differently?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM