2

我正在做一个小数据挖掘项目,其中 perl 脚本从 SQL 数据库中获取信息并对其进行解析。数据由几个时间戳组成。我想找出在任何特定日期存在多少特定类型的时间戳。不幸的是,这是我的第一个 perl 脚本,当涉及到散列和数组时 perl 的性质让我很困惑。

代码段:

my %values=();#A hash of the total values of each type of data of each day.
#The key is the day, and each key stores an array of each of the values I need.
my @proposal;
#[drafted timestamp(0), submitted timestamp(1), attny approved timestamp(2),Organiziation approved timestamp(3), Other approval timestamp(4), Approved Timestamp(5)]
while(@proposal=$sqlresults->fetchrow_array()){
 #TODO: check to make sure proposal is valid
 #Increment the number of timestamps of each type on each particular date
 my $i;
for($i=0;$i<=5;$i++)
$values{$proposal[$i]}[$i]++;
#Update rolling average of daily 
#TODO: To check total load, increment total load on all dates between attourney approve date and accepted date
for($i=$proposal[1];$i<=$proposal[2];$i++)
 $values{$i}[6]++; 
}

我不断在 for 循环递增值中遇到语法错误。另外,考虑到我正在使用严格和警告,当我在哈希中访问它们时,Perl 会自动创建正确值的数组,还是会到处出现越界错误?

感谢您的帮助,扎克

4

1 回答 1

5

错误:

for($i=0;$i<=5;$i++)
    $values{$proposal[$i]}[$i]++;
for($i=$proposal[1];$i<=$proposal[2];$i++)
    $values{$i}[6]++; 

Perl 不支持裸循环/条件块。或者更确切地说,确实如此,但不是这样。这可能适用于 PHP,但不适用于 Perl。您将需要将它们包含在块中:

for($i=0;$i<=5;$i++) {
    $values{$proposal[$i]}[$i]++;
}
for($i=$proposal[1];$i<=$proposal[2];$i++) {
    $values{$i}[6]++;
}

$values{$proposal[$i]}[$i]++;

由于 Perl 中的散列只能在其中容纳标量数据类型,为了将整个数组存储在散列中,我们将不得不通过引用来完成。这是关于数组引用的快速教程:

my $arr_ref = [];               # empty array reference
my $arr_ref = [ 1, 2, 'foo', ]; # initialize with values
my $arr_ref = \@arr;            # reference an existing array;
                                # does not make copy, but provides a
                                # read-write handle to the array

$arr_ref->[0];                  # index the first (index 0) element of the array
@{$arr_ref}[ 0 .. 4 ];          # index elements number one through five (0-4) of the array
                                # through what's called an "array slice"

您上面的代码所做的是将 hash key 的值从 hash 中提取$proposal[$i]出来%values,然后将其(标量)用作数组(它不是数组)。

正如我之前所说,您可以将其用作数组引用,但不能用作数组:

                    # v-- note the arrow
$values{$proposal[$i]}->[$i]++;

建议:

  • 写作my $foo; for ($foo = 0; $foo <= 5; $foo++)更容易写成“ for my $foo (0 .. 5)”或“ foreach my $foo (0 .. 5)”。本质上,这就是大多数人的做法。值得注意的是,forforeach是可以互换的——这是一个偏好和易读性的问题。

  • 为便于阅读,请使用多个空格缩进您的代码。一个好的经验法则是四个空格或一个制表符。St. Larry Wall 在设计 Perl 时正在考虑人们说和写的语言。

  • 我建议研究编写for循环的正确(正确,在这里,意思是最有效的)方法。如果程序有很多长for循环,则有一些习惯可以使程序总体上更快。例如:

    • ++$foo比 更有效$foo++。这源于内部:
      • $foo++递增变量,从中减去 1,然后返回结果,而
      • ++$foo递增变量并返回它。更少的操作 = 更快。
    • 小于或等于比较的效率低于普通的小于比较。同样,这是由于您的计算机必须执行的操作数量。for ($x=0; $x<=5; ++$x)最好写成for ($x=0; $x<6; ++$x).
  • Perl 有一些很棒的循环控制。有些,如map,非常强大。

于 2010-06-01T19:24:28.183 回答