【问题标题】:Iterating through an array in Perl遍历 Perl 中的数组
【发布时间】:2015-04-16 21:51:49
【问题描述】:

我正在学习 Perl 教程,但对于如何在调用库时遍历数组感到有些困惑

该库应包含一个函数,该函数接受一个数字数组(任意大小)。然后,该函数将计算数字的平均值、所有数字的总和以及一个新的数字数组,该数组由原始输入数字除以 2 组成。然后它将返回一个包含所有数字的新列表这些信息。

脚本文件,应该通过标准输入从用户那里得到一个数字列表,调用库函数并打印返回的数字。

到目前为止,我在主脚本中有这个:

  #!/usr/local/bin/perl

  require 'test4lib.pl';

  my @numbers;

  while (<>) {
      s/\s+\z//;
      last if $_ eq "";
      push @numbers, $_;
  }
  print "My Numbers are:  @numbers\n";
  number_crunch(@numbers);

  print "Total is: $total\n";
  print "Average is: $Average\n";
  print "Divided by 2 is: @divided_by\n";

还有这个在库函数中:

  sub number_crunch {
    foreach $number(@_) {
      $total = $sum+=$_ for (@_);
      $count = $numelements=(@_);

      $Average = ($total / $count);
      print "Total is: $total\n";
      $Average = ($total / $count);
      print "Average is: $Average\n";

      @divided_by = ();
      foreach (@_) {
        $new_number = $_ / 2;
        push @divided_by, $new_number;
      }
    }
  }
  1;

问题是库中的函数只获取数组的第一个数字,我不确定如何遍历数组。任何帮助表示赞赏。

贝基

【问题讨论】:

  • 欢迎使用 stackoverflow。 perl 的标准建议是 use strict; use warnings;
  • 这有很多问题。您遍历所有传递的数字,将当前数字传递给$number,但从不使用该变量,然后您尝试计算该循环中所有数字的$total,但为此您使用名为$sum的东西,您从未设置过,您为每个数字计算两次$average(因为您仍在循环中)等等......您需要退后一步,在重写之前考虑您的子流程。是的,在你真正知道自己在做什么之前,永远不要在没有strictwarnings 的情况下编写 perl 脚本。我什至不会说,但那是我。

标签: perl


【解决方案1】:

正如我在评论中解释的那样,您的代码还有其他问题,但让我仍然回答您关于如何将数组正确传递到子例程的问题。

您只使用数组作为参数并直接访问@_ 的方式实际上确实有效,只要您只想传递一个数组:

use strict;
use warnings;

my @array = (1, 2, 3);

foo(@array);

sub foo
{
    foreach my $num (@_)
    {
        print "$num\n";
    }
}

然而,这里实际发生的是你的数组变成了一个列表并被传递,并且该列表的内容存储在@_ 中。如果你想传递两个未知长度的数组,这很快就会成为一个问题,因为它们的所有元素都将在@_ 中相互跟随。

将数组(或哈希或其他任何东西)传递给 subs 时,更好的做法是使用引用:

use strict;
use warnings;

my @array = (1, 2, 3);

foo(\@array);

sub foo
{
    my @passedArray = @{$_[0]}; #Interpret the reference passed to us first as an array
    foreach my $num (@passedArray)
    {
        print "$num\n";
    }
}

在这种情况下,我将数组复制为子中的第一件事。我在这里这样做是为了使其更具可读性,但它也出于安全目的。由于这是通过引用传递的,如果您要直接处理 @{$_[0]} 并对其进行更改,这些更改也会显示在子外部的 @array 中。当然,在许多情况下,这正是人们想要的。比较:

use strict;
use warnings;

my @array = (1, 2, 3);

square(\@array);

foreach my $num (@array)
{
    print "$num\n";
}

sub square
{
    foreach my $num (@{$_[0]})
    {
        $num *= $num;
    }
}

【讨论】:

  • 请不要鼓励人们使用'&'来调用子程序。二十年来一直没有必要,它可能会产生令人困惑的副作用。
  • 我不明白您所说的“不产生警告”是什么意思。在任何情况下foo() 都不会产生警告,而&amp;foo() 不会。 &amp; 在调用子程序时根本没有必要,因此它变成了毫无意义的标点符号,只会让从未见过它的程序员感到困惑。原型与它无关。大多数子程序不应该有原型。 “可能令人困惑”的副作用是当您调用 &amp;foo(在大多数人看来,这与 &amp;foo() 没有太大区别)并且 Perl 传递 foo@_ 的当前值而不是一个空数组。
  • 哦。我看到您已经 a) 删除了我刚刚回复的评论,并且 b) 删除了 & 符号。谢谢。
  • @DaveCross 可以做很多不必要的事情。我承认,在这种情况下,代码更干净,没有空原型和 & 符号,覆盖它。回答您对我已删除的答案的回答(这可能是个好主意^^):&符号会抑制原型检查。所以它与原型有关。因此,它还抑制了原型检查警告(例如,缺少前向声明会产生)。但是,是的,在这种情况下,没有理由使用原型,也没有理由使用 & 符号,因此我删除了我的评论。 ^^
  • 哦,我知道&amp; 禁止原型检查。但是如果你使用原型,那么你不应该压制它们。如果你不使用它们,就没有必要压制它们。简而言之,我想不出在任何情况下都需要使用 & 符号或导致代码更清晰。请参阅我对this blog post 的评论,以更详细地阐述我对该主题的想法(我应该在某个时候将其变成博客文章)。
猜你喜欢
  • 2021-12-06
  • 2013-12-11
  • 1970-01-01
  • 2019-01-13
  • 2013-11-10
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
相关资源
最近更新 更多