【问题标题】:Perl: undef value in %hash -- why?Perl:%hash 中的 undef 值——为什么?
【发布时间】:2014-07-06 15:01:45
【问题描述】:

下午好。我正在将一些键和值写入 %hash,但我不断得到一个我似乎无法解释的 undef 值。

my @maxent_unchanged = <FILE1>; 
close FILE1;
chomp (@maxent_unchanged);

my @NM;
my @max_score_unchanged;
foreach my $line(@maxent_unchanged) {

  if ($line =~ m/[a-z]/i) {
    push (@NM, $line);
  }
  else { 
    push (@max_score_unchanged, $line);
  }
}

my %max_unchanged;
my $i = 0;
foreach my $lines(@maxent_unchanged) {
  $max_unchanged{$NM[$i]} = $max_score_unchanged[$i]; ##maxent score for unchanged seq
  $i++;
}

具体来说,@maxent_unchanged 在@NM 和@max_score_unchanged 之间交替,如下所示:

$VAR1 = 'TTAAGGCAGCCCACCCGCAGGCT        >       1       110740688       110740688       C       T       GCCTGGGCGGGGAGGGCTGTCACAGTGCCGGCAGCAGCCCTTAAGGCAGC[C]CACCCGCAGGCTGCCGAGCGCTACCTGTATTTCCCCAACTGGGCCATGGC splicing  splicing        SLC6A17:NM_001010898:exon12:c.1816-10C>T';
$VAR2 = '0.77';
$VAR3 = 'TTCTATCCTTTGTTTTACAGGAA        >       1       111857154       111857154       T       C       TTAAATGGAGGGAGTCCTGACTTTTGAAGTTTATCTGTTTCTATCCTTTG[T]TTTACAGGAACAGCCAGCTGAAAACTCTCCTGGCCATTGGAGGCTGGAAC splicing  splicing        CHIA:NM_201653:exon5:c.258-8T>C';
$VAR4 = '10.99';

因此它(@maxent_unchanged)的行数是@NM 和@max_score_unchanged 的​​两倍。我已经检查过了,它是正确的。

如果我转储 @NM 和 @max_score_unchanged 数据,我会得到相同数量的变量,但是当我将它们放入 %hash 时,我会得到一个额外的键值对,如数据转储哈希所示。

$VAR1 = '';
$VAR2 = undef;
$VAR3 = 'TTTTATTAATTCCTTTGTAGAAC        >       6       144835040       144835040       T       C       TATCATCTTAAATATTTCATATGGTTATGTAAGCATTTTATTAATTCCTT[T]GTAGAACCATCAGAACCAGCTAGAAATATTTGATGGGAACGTGGCTCACA splicing  splicing        UTRN:NM_007124:exon35:c.4945-5T>C';
$VAR4 = '8.22';
$VAR5 = 'TCTTTTTTGGACATGTACAGAGC        >       10      97127462        97127462        C       A       AGGAGTCTCTGAAGAAATTTCCGGAGTAGGGCTGATGGCTGAGCTCTGTA[C]ATGTCCAAAAAAGAAAAAAAAGAAGAAAAAAATAATGTAGATGATTTATT splicing  splicing        SORBS1:NM_001034957:exon13:c.1024-6G>T,NM_001034955:exon21:c.1972-6G>T,NM_001034956:exon18:c.1459-6G>T,NM_006434:exon13:c.1024-6G>T,NM_015385:exon17:c.1420-6G>T,NM_001034954:exon21:c.1906-6G>T,NM_024991:exon17:c.1147-6G>T';
$VAR6 = '4.43';

我的钥匙是独一无二的,所以我知道这不是问题所在。任何想法为什么?

其次,由于我想删除空的哈希键和值,我该怎么做?

非常感谢您的耐心等待和提前帮助, E

【问题讨论】:

    标签: perl hash


    【解决方案1】:

    在此循环中,您正在迭代 @maxent_unchanged,但您应该迭代 @max_score_unchanged。

    foreach my $lines(@max_score_unchanged) {
      $max_unchanged{$NM[$i]} = $max_score_unchanged[$i]; ##maxent score for unchanged seq
      $i++;
    }
    

    @maxent_unchanged 是您加载所有数据的位置,因此它的行数是@NM 和@max_score_unchanged 的两倍。

    如果你use strict; 和use warnings,你会在运行时看到这个错误:

    Use of uninitialized value within @NM in hash element at test.pl line 25, <DATA> line 4.
    Use of uninitialized value within @NM in hash element at test.pl line 25, <DATA> line 4.
    

    这会将您指向正确的行。您可以将print "$i\n"; 添加到该循环中以查看它经过了多少次,并将其与@NM 和@max_score_unchanged 的长度进行比较。

    我建议您在代码中使用适当的缩进以使其更具可读性。


    示例:

    use strict;
    use warnings;
    use Data::Dumper;
    
    my @maxent_unchanged = <DATA>;
    chomp (@maxent_unchanged);
    
    my @NM;
    my @max_score_unchanged;
    
    foreach my $line(@maxent_unchanged) {
        if ($line =~ m/[a-z]/i) {
            push (@NM, $line);
        }
        else { 
            push (@max_score_unchanged, $line);
        }
    }
    
    my %max_unchanged;
    for (my $i = 0; $i < @max_score_unchanged; $i++ ) {
        $max_unchanged{$NM[$i]} = $max_score_unchanged[$i]; ##maxent score for unchanged seq
    }
    
    print Dumper \%max_unchanged;
    
    __DATA__
    TTAAGGCAGCCCACCCGCAGGCT        >       1       110740688       110740688       C       T       GCCTGGGCGGGGAGGGCTGTCACAGTGCCGGCAGCAGCCCTTAAGGCAGC[C]CACCCGCAGGCTGCCGAGCGCTACCTGTATTTCCCCAACTGGGCCATGGC splicing  splicing        SLC6A17:NM_001010898:exon12:c.1816-10C>T
    0.77
    TTCTATCCTTTGTTTTACAGGAA        >       1       111857154       111857154       T       C       TTAAATGGAGGGAGTCCTGACTTTTGAAGTTTATCTGTTTCTATCCTTTG[T]TTTACAGGAACAGCCAGCTGAAAACTCTCCTGGCCATTGGAGGCTGGAAC splicing  splicing        CHIA:NM_201653:exon5:c.258-8T>C
    10.99
    

    我还举了一个示例,说明如何在 for 循环上使用索引进行迭代,而不是使用 foreach 循环,因为您不会在任何地方使用 $lines。


    输出:

    $VAR1 = {
              'TTAAGGCAGCCCACCCGCAGGCT        >       1       110740688       110740688       C       T       GCCTGGGCGGGGAGGGCTGTCACAGTGCCGGCAGCAGCCCTTAAGGCAGC[C]CACCCGCAGGCTGCCGAGCGCTACCTGTATTTCCCCAACTGGGCCATGGC splicing  splicing        SLC6A17:NM_001010898:exon12:c.1816-10C>T' => '0.77',
              'TTCTATCCTTTGTTTTACAGGAA        >       1       111857154       111857154       T       C       TTAAATGGAGGGAGTCCTGACTTTTGAAGTTTATCTGTTTCTATCCTTTG[T]TTTACAGGAACAGCCAGCTGAAAACTCTCCTGGCCATTGGAGGCTGGAAC splicing  splicing        CHIA:NM_201653:exon5:c.258-8T>C' => '10.99'
            };
    

    【讨论】:

    • 英雄!谢谢你。这么简单,却让小姐姐很开心!
    【解决方案2】:

    您真的需要将数据复制到多个数组中吗?是否在脚本的其他地方使用。如果没有,那么我会在遍历文件句柄时简单地构建哈希。

    use strict;
    use warnings;
    use Data::Dumper;
    
    my %max_unchanged;
    
    while (my $line = <DATA>) {
        chomp $line;
        if ($line =~ /^[ACGT]/) {
            chomp(my $value = <DATA>);
            $max_unchanged{$line} = $value;
        }
    }
    
    print Dumper \%max_unchanged;
    
    __DATA__
    TTAAGGCAGCCCACCCGCAGGCT        >       1       110740688       110740688       C       T       GCCTGGGCGGGGAGGGCTGTCACAGTGCCGGCAGCAGCCCTTAAGGCAGC[C]CACCCGCAGGCTGCCGAGCGCTACCTGTATTTCCCCAACTGGGCCATGGC splicing  splicing        SLC6A17:NM_001010898:exon12:c.1816-10C>T
    0.77
    TTCTATCCTTTGTTTTACAGGAA        >       1       111857154       111857154       T       C       TTAAATGGAGGGAGTCCTGACTTTTGAAGTTTATCTGTTTCTATCCTTTG[T]TTTACAGGAACAGCCAGCTGAAAACTCTCCTGGCCATTGGAGGCTGGAAC splicing  splicing        CHIA:NM_201653:exon5:c.258-8T>C
    10.99
    

    【讨论】:

      【解决方案3】:

      Matt 已正确指出您的问题的原因。事实上,在这种情况下,迭代一个 list 索引会更好,就像这样

      my %max_unchanged;
      for my $i (0 .. $#max_score_unchanged) {
        $max_unchanged{$NM[$i]} = $max_score_unchanged[$i];
      }
      

      或者你甚至可以像这样使用map

      my %max_unchanged = map {
        $NM[$_] => $max_score_unchanged[$_];
      } 0 .. $#max_score_unchanged;
      

      但最终没有明确的理由将您的文件分成两个数组,您可能更喜欢这个更简洁的程序版本,它可以达到相同的目的。它期望输入文件作为命令行上的参数。

      use strict;
      use warnings;
      
      my %max_unchanged;
      while (my $key = <>) {
        next unless $key =~ /[a-z]/;
        chomp $key;
        chomp($max_unchanged{$key} = <DATA>);
      }
      
      use Data::Dump;
      dd \%max_unchanged;
      

      鉴于您的示例输入数据,%max_unchanged 最终看起来像这样

      {
        "TTAAGGCAGCCCACCCGCAGGCT        >       1       110740688       110740688       C       T       GCCTGGGCGGGGAGGGCTGTCACAGTGCCGGCAGCAGCCCTTAAGGCAGC[C]CACCCGCAGGCTGCCGAGCGCTACCTGTATTTCCCCAACTGGGCCATGGC splicing  splicing        SLC6A17:NM_001010898:exon12:c.1816-10C>T" => 0.77,
        "TTCTATCCTTTGTTTTACAGGAA        >       1       111857154       111857154       T       C       TTAAATGGAGGGAGTCCTGACTTTTGAAGTTTATCTGTTTCTATCCTTTG[T]TTTACAGGAACAGCCAGCTGAAAACTCTCCTGGCCATTGGAGGCTGGAAC splicing  splicing        CHIA:NM_201653:exon5:c.258-8T>C"          => 10.99,
      }
      

      【讨论】:

        猜你喜欢
        • 2010-12-11
        • 1970-01-01
        • 2015-12-02
        • 2020-09-29
        • 2013-03-09
        • 2010-11-19
        • 1970-01-01
        • 2011-04-15
        • 1970-01-01
        相关资源
        最近更新 更多