【问题标题】:Multiple values in a hash for a single key单个键的哈希中的多个值
【发布时间】:2012-11-06 01:00:16
【问题描述】:

我有两个文件。 一个由一个唯一的列表组成,而另一个是一个带有年龄的冗余列表。

例如

File1:      File2:
Gaia        Gaia 3
Matt        Matt 12
Jane        Gaia 89
            Reuben 4

我的目标是匹配 File1 和 File2 并检索每个名称的最高年龄。 到目前为止,我已经编写了以下代码。 不太好用的一点是:当在哈希中找到相同的键时,打印更大的值。

欢迎任何建议/评论!

谢谢!!

#!/usr/bin/perl -w
use strict;

open (FILE1, $ARGV[0] )|| die "unable to open arg1\n"; #Opens first file for comparison
open (FILE2, $ARGV[1])|| die "unable to open arg2\n"; #2nd for comparison

my @not_red = <FILE1>;
my @exonslength = <FILE2>;

#2)  Produce an Hash of File2. If the key is already in the hash, keep the couple key-          value with the highest value. Otherwise, next.

my %hash_doc2;
my @split_exons;
my $key;
my $value;

foreach my $line (@exonslength) {

    @split_exons = split "\t", $line;

    @hash_doc2 {$split_exons[0]} = ($split_exons[1]);

 if (exists $hash_doc2{$split_exons[0]}) {

    if ( $hash_doc2{$split_exons[0]} > values %hash_doc2) {

     $hash_doc2{$split_exons[0]} = ($split_exons[1]);

    } else {next;}
       }
   }

#3) grep the non redundant list of gene from the hash with the corresponding value

my @a =  grep (@not_red,%hash_doc2);
print "@a\n";

【问题讨论】:

  • 请使用代码包装提交两个输入文件的内容

标签: perl select hash


【解决方案1】:

您需要保留所有值吗?如果没有,只能保留最大值:

@split_exons = split "\t", $line;
if (exists $hash_doc2{$slit_exons[0]}
    and $hash_doc2{$slit_exons[0]} < $split_exons[1]) {
    $hash_doc2{$split_exons[0]} = $split_exons[1];
}

您的代码也不会保留所有值。您不能将数组存储到哈希值中,您必须存储引用。向数组添加新值可以由push 完成:

push @{ $hash_doc2{$split_exons[0]} }, $split_exons[1];

您对values 的数值比较也没有按照您的想法进行。 &lt; 运算符强加了一个标量上下文,因此 values 返回值的数量。另一种选择是存储排序的值并始终要求最高值:

$hash_doc2{$split_exons[0]} = [ sort @{ $hash_doc2{$split_exons[0]} }, $split_exons[1] ];
# max for $x is at $hash_doc2{$x}[-1]

【讨论】:

    【解决方案2】:

    您可以循环遍历并逐行处理数据文件,而不是将整个 file2 读入一个数组(如果它很大,那就不好了):

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use autodie;
    use Data::Dumper;
    
    open( my $nameFh, '<', $ARGV[0]);
    open( my $dataFh, '<', $ARGV[1]);
    
    my $dataHash = {};
    my $processedHash = {};
    
    while(<$dataFh>){
        chomp;
        my ( $name, $age ) = split /\s+/, $_;
        if(! defined($dataHash->{$name}) or $dataHash->{$name} < $age ){
            $dataHash->{$name} = $age
        }
    }
    
    while(<$nameFh>){
        chomp;
        $processedHash->{$_} = $dataHash->{$_} if defined $dataHash->{$_};
    }
    
    print Dumper($processedHash);
    

    【讨论】:

      猜你喜欢
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-04
      相关资源
      最近更新 更多