Perl - 跨模块的数组哈希

时间:2011-07-21 19:52:55

标签: arrays perl hash

我对Perl有点新意,我需要一些关于在阵列之间移动我的Hash of Arrays的帮助。

目前我有一个db模块,它存储一个像这样的数组:

    sub getSourceCriteria {

    my($self) = shift();
    my($sourceId) = shift();
    chomp $sourceId;

    my(%criteria) =();
    $logger->debug("Getting records for Source ID: " . $sourceId);
    $dbh=DBI->connect('dbi:ODBC:StkSkrnDB', 'RTETET', 'XXuser01',{ RaiseError => 1, AutoCommit => 0 }) || \ 
               $logger->err_die("Database connection not made: $DBI::errstr\n");

    my($sth) =    "select a.criteria_id, a.criteria_type, a.criteria_props,a.generalcriteria_id,b.field_id ";
    $sth = $sth . "from t_criteria a, t_sourceMapping b where a.generalcriteria_id = (select generalcriteria_id from t_sourcecriteria where source_id =?) ";
    $sth = $sth . "and a.criteria_id=b.criteria_id";


    my($qry) = $dbh->prepare($sth);
    $qry->execute($sourceId) || $logger->error("Could not query for Source Criteria: $DBI::errstr\n");
    my(@row)=();
    my($tempCount) = 0;

    while ( @row = $qry->fetchrow_array ) {
        $tempCount = scalar @row;
        $logger->debug("Size of retrieved SQL Array : $tempCount");
        $criteria{$row[0]} = \@row;
        ##@{$criteria{$row[0]} } = \@row;


  }

  return %criteria;
}

我有一个单独的perl脚本,它从上面的代码中读取SQL输出:

    foreach my $criteria (keys %criterias) { 
        @temp = exists( $criterias{$criteria} ) ? @{ $criterias{$criteria} } : ();
        ##my $tempStr = exists( $criterias{$criteria} ) ? "Yes" : "No";
        $arraySize = scalar @temp;
        $logger->debug("GENERALCRITERIA_ID is $GENERALCRITERIA_ID and size of array is $arraySize and $temp[0]");
        $genCrit_ID = $temp[$GENERALCRITERIA_ID];
        $logger->debug("Criteria ID $criteria has Gen Criteria ID $genCrit_ID");
        if (0!=$generalCriteria_ID || $generalCriteria_ID != $genCrit_ID ) { ## test for uniqueness
            $generalCriteria_ID = -1;
        }
        else {
            $generalCriteria_ID = $genCrit_ID;
        }
    }# do something with $key and $value 
    $generalCriteria = $generalCriteria_ID;

}

问题是我一直得到0作为检索到的数组大小(第2个片段),即使我存储数组(在第1个片段中)我检查并获得实际的数组大小。

非常感谢任何帮助/澄清。

修改 在数据库接口代码中添加了更多代码。

1 个答案:

答案 0 :(得分:3)

while循环中,您将分配给@row,然后存储对该数组的引用。但是,每次循环迭代时,您将替换@row的内容而不声明新数组。所以最后,你的每个参考都指向同一个东西。

在您的代码中:

my(@row)=();
my($tempCount) = 0;

while ( @row = $qry->fetchrow_array ) {
    $tempCount = scalar @row;
    $logger->debug("Size of retrieved SQL Array : $tempCount");
    $criteria{$row[0]} = \@row;
    ##@{$criteria{$row[0]} } = \@row;
}

每次while循环迭代时,都会为@row数组赋值。但由于my(@row)=();行发生在循环之外,@row数组始终是相同的。因此,每次分配给数组时,您都要更改已经在所有引用中存储的内容。

要解决此问题,您需要为每次迭代声明一个新数组。最简单的方法是将声明移入while条件:

my($tempCount) = 0;

while ( my @row = $qry->fetchrow_array ) {
    $tempCount = scalar @row;
    $logger->debug("Size of retrieved SQL Array : $tempCount");
    $criteria{$row[0]} = \@row;
    ##@{$criteria{$row[0]} } = \@row;
 }

现在,每次参考\@row时,您都会获得对新数组的引用。


如果您的$qry->fetchrow_array方法返回了数组引用,则不会出现此问题:

my $row;
while ($row = $qry->fetchrow_array) {
    $logger->debug("Size of retrieved SQL Array : ".@$row);
    $criteria{$$row[0]} = $row;  # already a reference
 }

但我仍然会在我自己的代码中将其写为while (my $row = ...,因为保持范围较小是一件好事。