如何将数组的每个元素添加到另一个数组的每个元素?

时间:2018-06-21 04:14:41

标签: arrays perl

我有这些数组集合,每个数组都有两个元素。

@a = ("a", "b");

@i = (1, 2);

@s = ( "\\!", "\?");

如何使结果返回

a1!,  b2?

我需要它们是像这样的数组的新集合

@new =(a1!,b2?)

我编写了用于输出答案的代码

$i = length(@a);

for (0..$1) {

    @array = push(@array, @a[$i], @s[$i];

}

print @array;

但是,它仅返回

syntax error at pra.pl line 10, near "];"

谢谢。

4 个答案:

答案 0 :(得分:4)

您有一个基本的想法,那就是使用数组的索引同时进行迭代。但是该代码有许多基本错误,并且也不能像示例所示那样进行。我建议先全面了解现代的Perl教程。

示例表明您要在每个索引处串联(请参见. operator)元素

use warnings;
use strict;
use feature 'say';

my @a1 = ('a', 'b');
my @a2 = (1, 2);
my @a3 = ('!', '?');

my @res;
foreach my $i (0..$#a1) {
    push @res, $a1[$i] . $a2[$i] . $a3[$i];
}

say for @res;

其中$#a1是数组@a1的最后一个元素的索引。假设所有数组的大小都相同,并且所有元素都已定义。

这项精确的工作可以在一条语句中使用map完成

my @res = map { $a1[$_] . $a2[$_] . $a3[$_] } 0..$#a1;

具有相同的严肃假设。即使您知道他们持有,您是否肯定在每次运行任何数据时都 ?有关可靠的方法,请参见answer by mwp

each_array中还有List::MoreUtils,为所有数组提供“同时迭代器”

my $ea = each_array(@a1, @a2, @a3);

my @res;
while ( my ($e1, $e2, $e3) = $ea->() ) {
    push @res, $e1 . $e2 . $e3
}

对于更复杂的处理真的很有用。

快速浏览基础知识

  • 程序的开头始终带有use warnings;use strict;。他们将捕获许多错误,否则将花费很多时间和神经。

  • 不要使用单字母变量名称。我们很快就忘记了它们的含义,并且代码变得难以遵循,而且它们也很容易造成愚蠢的错误。

  • {li>

    数组的大小不是length给出。通常使用context获得它-将数组分配给标量时,将返回其元素数。对于索引上的迭代,有$#ary,即@ary的最后一个元素的索引。然后,索引列表为0 .. $#ary,使用range (..) operator

  • 标识符(变量名)开头的符号($@%)表示type of the variable(标量,数组,哈希)。数组元素是标量,因此需要$-$ary[0]

  • push不会返回数组元素,而是将其后面列表中的标量添加到其第一个参数中的数组。

  • print @array;打印数组元素,它们之间没有任何内容。引用时会添加空格,print "@array\n";。不过请注意方便的feature say,它将添加新行。

答案 1 :(得分:4)

use 5.008;
use List::AllUtils qw(zip_by);
⋮
my @new = zip_by { join '', @_ } \@a, \@i, \@s;

zip_by是CPAN上List::AllUtils模块的子例程。因此它不是内置的。


use v6;
⋮
my @new = map { .join }, zip @a, @i, @s;

在Perl 6中,zip已经成为标准库的一部分。这种额外的解决方案在这里很有用,这是一个展示优势的机会:可以完成相同的工作,但是语法比较少,并且可以立即使用。

v6并非绝对必要,在这里我只是将其用作对比来表示版本。但是在文件的开头,它还具有不错的属性,如果您不小心在Perl 5中运行了Perl 6代码,您将得到一个不错的错误消息,而不是一个隐秘的语法错误。尝试一下!来自use VERSION documentation

  

如果VERSION大于当前Perl的版本,则会引发异常。

答案 2 :(得分:2)

  1. 总是use strict;use warnings;(并使用my声明变量)。
  2. 您不需要在Perl字符串中转义?!,并且可以使用qw//类似引号的运算符来轻松构建术语列表。
  3. 您正在使用length(@a)来确定最后一个索引,但是Perl数组索引是从零开始的,因此最后一个索引实际上是length(@a) - 1。 (但这仍然不正确。请参阅下一点...)
  4. 要在Perl中获得数组的长度,您想在标量上下文中对其进行求值。 length函数用于字符串。
  5. 您还没有考虑数组长度都不相同的情况。
  6. 您将最后一个索引分配给变量$i,但随后在下一行引用了变量$1。这是两个不同的变量。
  7. 您要从零开始迭代到最后一个索引,但没有将迭代器显式分配给变量,也没有使用隐式迭代器变量($_)。
  8. 要在Perl中按索引获取单个数组元素,语法为$a[$i],而不是@a[$i]。因为只需要一个标量值,所以表达式必须以标量符号$开头。 (相反,如果您希望从表达式中获取值列表,则可以使用数组@来表示该表达式。)
  9. push修改第一个参数给出的数组,因此无需将结果分配回表达式中的数组。
  10. 您在push表达式中缺少右括号。
  11. 在相同的代码中,您拥有@new@array,并且仅添加了@a@s中的元素(即您忘记了@i )。
  12. 您正在将元素压入数组,但没有将它们串联为所需的字符串格式。

这是您的实现的有效版本:

use strict;
use warnings;

use List::Util qw{max};

my @a = ("a", "b");
my @i = ("1", "2");
my @s = ("!", "?");

my @array;
my $length = max scalar @a, scalar @i, scalar @s;

foreach my $i (0 .. $length - 1) {
  push @array, ($a[$i] // '') . ($i[$i] // '') . ($s[$i] // '');
}

print @array;

//的意思是“定义或”。

这是我的写法:

use strict;
use warnings;

use List::Util qw{max};

my @a = qw/a b/;
my @i = qw/1 2/;
my @s = qw/! ?/;

my @array = map {
  join '', grep defined, $a[$_], $i[$_], $s[$_]
} 0 .. max $#a, $#i, $#s;

print "@array\n";

$#a的意思是“给我数组@a的最后一个元素的索引。”)

答案 3 :(得分:-1)

use warnings;
use strict;    
use Data::Dumper;

my $result = [];
my @a = ("a", "b");
my @i = (1, 2);
my @s = ( "\!", "\?");

my $index = 0;
for my $a ( @a ) {
  push( @$result, ($a[$index], $i[$index], $s[$index]) );
  $index = $index + 1;
}

print Dumper(@$result);