对具有多个条件的嵌套哈希进行排序

问题描述 投票:1回答:3

我对perl编程有点陌生,我得到了一个可以这样表示的哈希:

$hash{"snake"}{ACB2}   = [70, 120];
$hash{"snake"}{SGJK}   = [183, 120];
$hash{"snake"}{KDMFS}   = [1213, 120];
$hash{"snake"}{VCS2}   = [21, 120];
...
$hash{"bear"}{ACB2}   = [12, 87];
$hash{"bear"}{GASF}   = [131, 87];
$hash{"bear"}{SDVS}   = [53, 87];
...
$hash{"monkey"}{ACB2}   = [70, 230];
$hash{"monkey"}{GMSD}   = [234, 230];
$hash{"monkey"}{GJAS}   = [521, 230];
$hash{"monkey"}{ASDA}   = [134, 230];
$hash{"monkey"}{ASMD}   = [700, 230];

哈希的结构总结如下:

%hash{Organism}{ProteinID}=(protein_length, total_of_proteins_in_that_organism)

我想根据某些条件对该哈希进行排序。首先,我只想考虑蛋白质总数大于100的那些生物,然后我要显示该生物的名称以及最大的蛋白质及其长度。

为此,我要采用以下方法:

    foreach my $org (sort keys %hash) {
        foreach my $prot (keys %{ $hash{$org} }) {
            if ($hash{$org}{$prot}[1] > 100) {
                @sortedarray = sort {$hash{$b}[0]<=>$hash{$a}[0]} keys %hash;

                print $org."\n";
                print @sortedarray[-1]."\n";
                print $hash{$org}{$sortedarray[-1]}[0]."\n"; 
            }
        }
    }

但是,它打印生物体名称的次数是蛋白质总数的多少倍,例如,它打印“蛇” 120次。此外,这排序不正确,因为我想我应该在排序行中使用变量$ org和$ prot。

最后,输出应如下所示:

snake
"Largest protein": KDMFS [1213]

monkey
"Largest protein": ASMD [700]
perl multidimensional-array hash protein-database perl-hash
3个回答
2
投票

所有数据按打印顺序排序

use warnings;
use strict;
use feature 'say';

use List::Util qw(max);

my %hash;   
$hash{"snake"}{ACB2}   = [70, 120];
$hash{"snake"}{SGJK}   = [183, 120];
$hash{"snake"}{KDMFS}   = [1213, 120];
$hash{"snake"}{VCS2}   = [21, 120];
$hash{"bear"}{ACB2}   = [12, 87];
$hash{"bear"}{GASF}   = [131, 87];
$hash{"bear"}{SDVS}   = [53, 87];    
$hash{"monkey"}{ACB2}   = [70, 230];
$hash{"monkey"}{GMSD}   = [234, 230];
$hash{"monkey"}{GJAS}   = [521, 230];
$hash{"monkey"}{ASDA}   = [134, 230];
$hash{"monkey"}{ASMD}   = [700, 230];

my @top_level_keys_sorted = 
    sort {   
        ( max map { $hash{$b}{$_}->[0] } keys %{$hash{$b}} ) <=> 
        ( max map { $hash{$a}{$_}->[0] } keys %{$hash{$a}} )
    }   
    keys %hash;

for my $k (@top_level_keys_sorted) {
    say $k; 
    say "\t$_ --> @{$hash{$k}{$_}}" for 
        sort { $hash{$k}{$b}->[0] <=> $hash{$k}{$a}->[0] } 
        keys %{$hash{$k}};
}

打印

蛇KDMFS-> 1213 120SGJK-> 183120ACB2-> 70120VCS2-> 21120猴ASMD-> 700230GJAS-> 521230GMSD-> 234230ASDA-> 134230ACB2-> 70230熊GASF-> 131 87SDVS-> 53 87ACB2-> 12 87

我不知道输出是否应显示所有“ 蛋白质总数大于100的生物”(文本)还是仅显示最大的(期望输出),因此我将其全部保留。如果需要,请剪掉。

请注意,哈希本身不能被“排序”,因为它本质上是无序的。但是我们可以像上面那样打印出排序的内容,或者根据需要生成可以排序的辅助数据结构。


1
投票

您在使用吗

use strict;
use warnings;

在脚本的开头?这样至少可以突出一些问题的根源。没有它们,Perl会默默地做一些很容易指出是愚蠢,毫无意义甚至最有可能的编程错误的事情。


作业

$hash{"snake"}{ACB2}   = (70, 120);

将仅分配值120,因为该分配需要标量,但左侧有很多值。

要分配arrayref,必须明确声明它:

$hash{"snake"}{ACB2}   = [70, 120];

您对信号的使用($@%)似乎已关闭。

  • 如果要处理标量或单个数组或哈希值,请使用$。>>
  • 如果要处理数组(或数组或哈希片(多个值);例如,@将从数组@array[0,2]返回第一和第三项),请使用@array
  • 如果要处理哈希,请使用%
  • 所以

@sortedarray[-1]

应该是

$sortedarray[-1]

因为您只访问一个值。


1
投票

如果我对您的理解正确,那么下面的代码应该可以实现您所期望的。我将结果保留在哈希表中,可以随意打印任何格式的数据]

© www.soinside.com 2019 - 2024. All rights reserved.