0

我有一个包含 10 个数字的数组。我想在数组索引 0,2,4,6,8 中选择数字并将它们放入一个新数组中。索引 1,3,5,7,9 也是如此。我是 Perl 的新手(几天前开始)。

我的程序:

my @b;
@a = (1,2,3,4,5,6,7,8,9,10);
for($i=0;$i<=$#a;$i++)
   {
    push(@b,$a[$i+1]);
   }
print "@b";

我究竟做错了什么?

4

5 回答 5

2

我建议避免for使用循环,因为在使用中更容易出错,并使用foreach

my @a = (1,2,3,4,5,6,7,8,9,10);

my (@even, @odd);
foreach my $i (0 .. $#a) {

  if ($i % 2) { push @odd, $a[$i] } else { push @even, $a[$i] }
}

您还可以使用map来测试数组索引模%2,然后@even决定过滤它()或使用它取值$a[$_]

my @even = map { $_%2 ? () : $a[$_] } 0 .. $#a;
my @odd = map {  $_%2 ? $a[$_] : () } 0 .. $#a;
于 2013-06-12T21:08:33.903 回答
2

简单的。

my @a = (1,2,3,4,5,6,7,8,9,10);

my (@even, @odd);

for ( @a ) {
   $_ % 2 ? push @odd, $_ : push @even, $_;
}
于 2013-06-13T02:52:45.543 回答
1

一些东西:

  • 使用编译指示use strict;use warnings;. 这些会捕获很多错误。如果您使用,则必须使用(有时您会使用,但 99% 的情况下,您会使用)use strict;声明您的变量myourmy
  • 在您的for循环中,您使用的是默认变量$_。由于各种原因,这个变量是邪恶的。(一,它在范围内是全局的,所以其他东西可能会改变你的这个变量而你不会知道。)。声明您的变量,除非您必须使用$_.
  • 标准是把 和放在{一起。另一个是避免for 循环(并避免这只是 的别名)forwhileC styleforeachfor
  • 使用空格。它比阅读要容易$i <= $#a得多$i<=$a

这是我对您的程序的解释:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);  #A nicer 'print'

my @a = qw(12 13 14 15 16 17 18 19 20);
my @even;
my @odd;

for my $element (0..$#a) {
if ( $element % 2 ) {
    push @odd, $a[$element];
}
else {
    push @even, $a[$element];
}
}
say '@even = ' . join ': ', @even;
say '@odd = ' . join ': ', @odd;

输出:

@even = 12: 14: 16: 18: 20
@odd = 13: 15: 17: 19
  • 注意我的for循环。我使用0..$#a来遍历数组的每个元素。is 返回数组的$#最后一个索引。请注意,这比for($i=0;$i<=$#a;$i++)您使用的更容易理解。这是不鼓励 C 风格的 for 循环的原因之一。
  • 我使用模运算符%来解析我的偶数/奇数。模数类似于余数除法。如果数字是奇数,则模数% 2将为 1。否则,它为零。模运算非常适合在循环中工作的任何事物。

但是让我们回到你的程序。这是您的原始代码,并进行了一些小的调整。

  • 我添加了use strict;and use warnings;。这些可以捕获大约 99% 的编程错误。
  • 我使用use feature qw(say);因为say在调试方面更好。我可以拿一个声明,复制它,然后把qq(...);它扔到周围,看看它在做什么。
  • 我添加了一堆say语句来揭示代码的逻辑。

让我们看看会发生什么。这是您的程序稍作修改:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

my @b;
my @a = (1,2,3,4,5,6,7,8,9,10);
my $i;
for($i=0; $i<=$#a; $i++) {
    say "Index = $i  Element = $a[$i + 1]";
    say qq(push(\@b, $a[$i+1]););
    push(@b,$a[$i+1]);
}
print "@b";

这是输出:

Index = 0  Element = 2
push(@b, 2);
Index = 1  Element = 3
push(@b, 3);
Index = 2  Element = 4
push(@b, 4);
Index = 3  Element = 5
push(@b, 5);
Index = 4  Element = 6
push(@b, 6);
Index = 5  Element = 7
push(@b, 7);
Index = 6  Element = 8
push(@b, 8);
Index = 7  Element = 9
push(@b, 9);
Index = 8  Element = 10
push(@b, 10);
Use of uninitialized value in concatenation (.) or string at ./test.pl line 11.
Index = 9  Element = 
Use of uninitialized value within @a in concatenation (.) or string at ./test.pl line 12.
push(@b, );
Use of uninitialized value $b[9] in join or string at ./test.pl line 15.

我可以看到每个push语句是如何执行的,并且看一下,您正在推动每个元素。其实,你并不是因为你把它$a[$i+1]当做你在推动的东西。

使用use warnings并且我可以看到我正在尝试将不存在的内容推$a[10]送到您的@b数组中。

让我们更改您的for循环以转到其他所有元素

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

my @b;
my @a = qw(1 2 3 4 5 6 7 8 9 10);
my $i;
for ($i=0; $i <= $#a; $i += 2) {
    push @b, $a[$i];
}

第一个元素是$a[0]。循环中的下一个元素是$a[2]因为我添加2了索引,而不是仅仅将它增加1. 现在,我将遍历所有偶数元素并跳过所有奇数元素。

和输出:

1 3 5 7 9

(注意 $a[0] = 1。这就是为什么它们都是奇数。这就是我在12程序中开始的原因,所以 $a[0] = 12 是偶数)。

我的偏好是使用while并避免for(...; ...; ...)构造:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

my @b;
my @a = qw(1 2 3 4 5 6 7 8 9 10);
my $i = 0;
while ( $i < $#a ) {
    push @b, $a[$i];
    $i += 2;
}
于 2013-06-13T04:15:04.127 回答
1

List::MoreUtils有一个indexes功能:

use List::MoreUtils qw{indexes} ;
use 5.10.0 ;                                              
my @a = (1,2,3,4,5,6,7,8,9,10) ; 

# index of array where even
say foreach indexes { $_ % 2 == 0 } @a ;

# index of array where odd
say foreach indexes { $_ % 2 != 0 } @a ;

我承认这可能有点不雅,在这里使用模块可能是作弊 - 尤其是不在 CORE 中的模块。如果List::MoreUtils 并且List::Utils只是一个 CORE 模块会很方便,但仍然不如这里的其他一些答案那么优雅。

于 2013-06-13T04:15:05.953 回答
1

甚至:

for($i=0;$i<=$#a;$i+=2)
   {
    push(@b,$a[$i]);
   }

奇怪的:

for($i=1;$i<=$#a;$i+=2)
   {
    push(@b,$a[$i]);
   }
于 2013-06-12T21:09:58.687 回答