I have these sets of arrays which has two elements for each.
我有这些数组,每个数组都有两个元素。
@a = ("a", "b");
@i = (1, 2);
@s = ( "\\!", "\?");
How do I make the result such that it'll return
如何使结果返回
a1!, b2?
And I need them to be a new set of an array like
我需要它们成为一组新的数组
@new =(a1!,b2?)
I wrote the code for output of the answer
我写了答案输出的代码
$i = length(@a);
for (0..$1) {
@array = push(@array, @a[$i], @s[$i];
}
print @array;
However, it only returned
但是,它只返回了
syntax error at pra.pl line 10, near "];"
Thank you in advance.
先谢谢你。
4 个解决方案
#1
4
use 5.008;
use List::AllUtils qw(zip_by);
⋮
my @new = zip_by { join '', @_ } \@a, \@i, \@s;
zip_by
is a subroutine from the List::AllUtils
module on CPAN. So it's not built-in.
zip_by是CPAN上List :: AllUtils模块的子例程。所以它不是内置的。
use v6;
⋮
my @new = map { .join }, zip @a, @i, @s;
In Perl 6, zip
is already part of the standard library. This additionaly solution is here for flavour, it's an opportunity to show off strengths: does the same job, but with less syntax in comparison, and works out of the box.
在Perl 6中,zip已经是标准库的一部分。这个额外的解决方案在这里是为了味道,它是展示优势的机会:做同样的工作,但相比之下语法更少,并且开箱即用。
v6
is not strictly necessary, here I just used it for contrast to indicate the version. But at the beginning of a file it also has the nice property that if you accidentally run Perl 6 code in Perl 5, you'll get a nice error message instead of a cryptic syntax error. Try it! From the use VERSION
documentation:
v6并不是绝对必要的,这里我只是用它来对比来表示版本。但是在文件的开头它还有一个很好的属性,如果你不小心在Perl 5中运行Perl 6代码,你会得到一个很好的错误信息,而不是一个神秘的语法错误。尝试一下!从使用VERSION文档:
An exception is raised if VERSION is greater than the version of the current Perl
如果VERSION大于当前Perl的版本,则会引发异常
#2
4
The basic idea you have is good, to iterate simultaneously using index of an array. But the code has many elementary errors and it also doesn't do what the examples show. I suggest to first make a thorough pass through a modern and reputable Perl tutorial.
您拥有的基本想法是好的,使用数组的索引同时迭代。但代码有许多基本错误,它也没有做示例所示的内容。我建议首先彻底通过一个现代的,有信誉的Perl教程。
The examples indicate that you want to concatenate (see .
operator) elements at each index
这些示例表明您希望在每个索引处连接(请参阅。运算符)元素
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;
where $#a1
is the index of the last element of array @a1
. This assumes that all arrays are of the same size and that all their elements are defined.
其中$#a1是数组@ a1的最后一个元素的索引。这假设所有数组都具有相同的大小并且所有元素都已定义。
This exact work can be done using map in one statement
这个确切的工作可以在一个语句中使用map来完成
my @res = map { $a1[$_] . $a2[$_] . $a3[$_] } 0..$#a1;
with the same, serious, assumptions. Even if you knew they held, do you know for sure, in every run on any data? For a robust approach see the answer by mwp.
同样严肃的假设。即使你知道他们持有,你是否确实知道,在任何数据运行中?对于一个强大的方法,请参阅mwp的答案。
There is also each_array from List::MoreUtils, providing a "simultaneous iterator" for all arrays
List :: MoreUtils中还有each_array,为所有数组提供“同时迭代器”
my $ea = each_array(@a1, @a2, @a3);
my @res;
while ( my ($e1, $e2, $e3) = $ea->() ) {
push @res, $e1 . $e2 . $e3
}
which is really useful for more complex processing.
这对于更复杂的处理非常有用。
A quick run through basics
快速浏览基础知识
-
Always have
use warnings;
anduse strict;
at the beginning of your programs. They will catch many errors that would otherwise take a lot of time and nerves.始终有使用警告;并严格使用;在你的程序的开头。它们会捕获许多错误,否则会花费大量时间和精力。
-
Don't use single-letter variable names. We quickly forget what they meant and the code gets hard to follow, and they make it way too easy to make silly mistakes.
不要使用单字母变量名。我们很快忘记了他们的意思,代码很难遵循,而且他们很容易犯下愚蠢的错误。
-
Array's size is not given by
length
. It is normally obtained using context -- when an array is assigned to a scalar the number of its elements is returned. For iteration over indices there is$#ary
, the index of the last element of@ary
. Then the list of indices is0 .. $#ary
, using the range (..
) operator数组的大小不是按长度给出的。它通常使用上下文获得 - 当数组被分配给标量时,返回其元素的数量。对于索引的迭代,有$#ary,@ary的最后一个元素的索引。然后索引列表为0 .. $#ary,使用范围(..)运算符
-
The sigil (
$
,@
,%
) at the beginning of an identifier (variable name) indicates the type of the variable (scalar, array, hash). An array element is a scalar so it needs$
--$ary[0]
标识符(变量名)开头的sigil($,@,%)表示变量的类型(标量,数组,散列)。数组元素是一个标量因此它需要$ - $ ary [0]
-
The push doesn't return array elements but it rather adds to the array in its first argument the scalars in the list that follows.
push不返回数组元素,而是在第一个参数中向数组添加后面列表中的标量。
-
The
print @array;
prints array elements without anything between them. When you quote it spaces are added,print "@array\n";
. Note the handy featuresay
though, which adds the new line.打印@array;打印数组元素,它们之间没有任何东当你引用它时,会添加空格,打印“@array \ n”;.请注意这个方便的功能,但它添加了新的一行。
#3
2
- Always
use strict;
anduse warnings;
(and usemy
to declare variables). - 始终使用严格;并使用警告; (并使用我来声明变量)。
- You don't need to escape
?
and!
in Perl strings, and you can use theqw//
quote-like operator to easily build lists of terms. - 你不需要逃避?而且!在Perl字符串中,您可以使用qw // quote-like运算符轻松构建术语列表。
- You are using
length(@a)
to determine the last index, but Perl array indexes are zero-based, so the last index would actually belength(@a) - 1
. (But that's still not right. See the next point...) - 您使用长度(@a)来确定最后一个索引,但Perl数组索引是从零开始的,因此最后一个索引实际上是长度(@a) - 1.(但这仍然不正确。请参阅下一个点。 ..)
- To get an array's length in Perl, you want to evaluate it in scalar context. The
length
function is for strings. - 要在Perl中获取数组的长度,您需要在标量上下文中对其进行求值。长度函数用于字符串。
- You have not accounted for the situation when the arrays are not all the same length.
- 当阵列长度不同时,您没有考虑到这种情况。
- You assign the last index to a variable
$i
, but then you reference the variable$1
on the next line. Those are two different variables. - 您将最后一个索引分配给变量$ i,但随后在下一行引用变量$ 1。这是两个不同的变量。
- You are iterating from zero to the last index, but you aren't explicitly assigning the iterator to a variable, and you aren't using the implicit iterator variable (
$_
). - 您正在从零迭代到最后一个索引,但是您没有显式地将迭代器分配给变量,并且您没有使用隐式迭代器变量($ _)。
- To get a single array element by index in Perl, the syntax is
$a[$i]
, not@a[$i]
. Because you only want a single, scalar value, the expression has to start with the scalar sigil$
. (If instead you wanted a list of values from an expression, you would start the expression with the array sigil@
.) - 要在Perl中通过索引获取单个数组元素,语法为$ a [$ i],而不是@a [$ i]。因为你只需要一个标量值,所以表达式必须以标量符号$开头。 (如果您需要表达式中的值列表,则可以使用数组sigil @启动表达式。)
-
push
modifies the array given by the first argument, so there's no need to assign the result back to the array in the expression. - push修改第一个参数给出的数组,因此不需要将结果分配回表达式中的数组。
- You are missing a closing parenthesis in your
push
expression. - 您在推送表达式中缺少右括号。
- In your same code, you have
@new
and@array
, and you are only adding elements from@a
and@s
(i.e. you forgot about@i
). - 在同一个代码中,你有@new和@array,而你只是添加来自@a和@s的元素(即你忘记了@i)。
- You are pushing elements onto the array, but you aren't concatenating them into the desired string format.
- 您正在将元素推送到数组上,但您没有将它们连接成所需的字符串格式。
Here is a working version of your implementation:
以下是您的实施的工作版本:
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;
(The //
means "defined-or".)
(//表示“已定义 - 或”。)
Here's how I might write it:
这是我写它的方式:
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";
(The $#a
means "give me the index of the last element of the array @a
.")
($#a表示“给我数组@a的最后一个元素的索引。”)
#4
-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);
#1
4
use 5.008;
use List::AllUtils qw(zip_by);
⋮
my @new = zip_by { join '', @_ } \@a, \@i, \@s;
zip_by
is a subroutine from the List::AllUtils
module on CPAN. So it's not built-in.
zip_by是CPAN上List :: AllUtils模块的子例程。所以它不是内置的。
use v6;
⋮
my @new = map { .join }, zip @a, @i, @s;
In Perl 6, zip
is already part of the standard library. This additionaly solution is here for flavour, it's an opportunity to show off strengths: does the same job, but with less syntax in comparison, and works out of the box.
在Perl 6中,zip已经是标准库的一部分。这个额外的解决方案在这里是为了味道,它是展示优势的机会:做同样的工作,但相比之下语法更少,并且开箱即用。
v6
is not strictly necessary, here I just used it for contrast to indicate the version. But at the beginning of a file it also has the nice property that if you accidentally run Perl 6 code in Perl 5, you'll get a nice error message instead of a cryptic syntax error. Try it! From the use VERSION
documentation:
v6并不是绝对必要的,这里我只是用它来对比来表示版本。但是在文件的开头它还有一个很好的属性,如果你不小心在Perl 5中运行Perl 6代码,你会得到一个很好的错误信息,而不是一个神秘的语法错误。尝试一下!从使用VERSION文档:
An exception is raised if VERSION is greater than the version of the current Perl
如果VERSION大于当前Perl的版本,则会引发异常
#2
4
The basic idea you have is good, to iterate simultaneously using index of an array. But the code has many elementary errors and it also doesn't do what the examples show. I suggest to first make a thorough pass through a modern and reputable Perl tutorial.
您拥有的基本想法是好的,使用数组的索引同时迭代。但代码有许多基本错误,它也没有做示例所示的内容。我建议首先彻底通过一个现代的,有信誉的Perl教程。
The examples indicate that you want to concatenate (see .
operator) elements at each index
这些示例表明您希望在每个索引处连接(请参阅。运算符)元素
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;
where $#a1
is the index of the last element of array @a1
. This assumes that all arrays are of the same size and that all their elements are defined.
其中$#a1是数组@ a1的最后一个元素的索引。这假设所有数组都具有相同的大小并且所有元素都已定义。
This exact work can be done using map in one statement
这个确切的工作可以在一个语句中使用map来完成
my @res = map { $a1[$_] . $a2[$_] . $a3[$_] } 0..$#a1;
with the same, serious, assumptions. Even if you knew they held, do you know for sure, in every run on any data? For a robust approach see the answer by mwp.
同样严肃的假设。即使你知道他们持有,你是否确实知道,在任何数据运行中?对于一个强大的方法,请参阅mwp的答案。
There is also each_array from List::MoreUtils, providing a "simultaneous iterator" for all arrays
List :: MoreUtils中还有each_array,为所有数组提供“同时迭代器”
my $ea = each_array(@a1, @a2, @a3);
my @res;
while ( my ($e1, $e2, $e3) = $ea->() ) {
push @res, $e1 . $e2 . $e3
}
which is really useful for more complex processing.
这对于更复杂的处理非常有用。
A quick run through basics
快速浏览基础知识
-
Always have
use warnings;
anduse strict;
at the beginning of your programs. They will catch many errors that would otherwise take a lot of time and nerves.始终有使用警告;并严格使用;在你的程序的开头。它们会捕获许多错误,否则会花费大量时间和精力。
-
Don't use single-letter variable names. We quickly forget what they meant and the code gets hard to follow, and they make it way too easy to make silly mistakes.
不要使用单字母变量名。我们很快忘记了他们的意思,代码很难遵循,而且他们很容易犯下愚蠢的错误。
-
Array's size is not given by
length
. It is normally obtained using context -- when an array is assigned to a scalar the number of its elements is returned. For iteration over indices there is$#ary
, the index of the last element of@ary
. Then the list of indices is0 .. $#ary
, using the range (..
) operator数组的大小不是按长度给出的。它通常使用上下文获得 - 当数组被分配给标量时,返回其元素的数量。对于索引的迭代,有$#ary,@ary的最后一个元素的索引。然后索引列表为0 .. $#ary,使用范围(..)运算符
-
The sigil (
$
,@
,%
) at the beginning of an identifier (variable name) indicates the type of the variable (scalar, array, hash). An array element is a scalar so it needs$
--$ary[0]
标识符(变量名)开头的sigil($,@,%)表示变量的类型(标量,数组,散列)。数组元素是一个标量因此它需要$ - $ ary [0]
-
The push doesn't return array elements but it rather adds to the array in its first argument the scalars in the list that follows.
push不返回数组元素,而是在第一个参数中向数组添加后面列表中的标量。
-
The
print @array;
prints array elements without anything between them. When you quote it spaces are added,print "@array\n";
. Note the handy featuresay
though, which adds the new line.打印@array;打印数组元素,它们之间没有任何东当你引用它时,会添加空格,打印“@array \ n”;.请注意这个方便的功能,但它添加了新的一行。
#3
2
- Always
use strict;
anduse warnings;
(and usemy
to declare variables). - 始终使用严格;并使用警告; (并使用我来声明变量)。
- You don't need to escape
?
and!
in Perl strings, and you can use theqw//
quote-like operator to easily build lists of terms. - 你不需要逃避?而且!在Perl字符串中,您可以使用qw // quote-like运算符轻松构建术语列表。
- You are using
length(@a)
to determine the last index, but Perl array indexes are zero-based, so the last index would actually belength(@a) - 1
. (But that's still not right. See the next point...) - 您使用长度(@a)来确定最后一个索引,但Perl数组索引是从零开始的,因此最后一个索引实际上是长度(@a) - 1.(但这仍然不正确。请参阅下一个点。 ..)
- To get an array's length in Perl, you want to evaluate it in scalar context. The
length
function is for strings. - 要在Perl中获取数组的长度,您需要在标量上下文中对其进行求值。长度函数用于字符串。
- You have not accounted for the situation when the arrays are not all the same length.
- 当阵列长度不同时,您没有考虑到这种情况。
- You assign the last index to a variable
$i
, but then you reference the variable$1
on the next line. Those are two different variables. - 您将最后一个索引分配给变量$ i,但随后在下一行引用变量$ 1。这是两个不同的变量。
- You are iterating from zero to the last index, but you aren't explicitly assigning the iterator to a variable, and you aren't using the implicit iterator variable (
$_
). - 您正在从零迭代到最后一个索引,但是您没有显式地将迭代器分配给变量,并且您没有使用隐式迭代器变量($ _)。
- To get a single array element by index in Perl, the syntax is
$a[$i]
, not@a[$i]
. Because you only want a single, scalar value, the expression has to start with the scalar sigil$
. (If instead you wanted a list of values from an expression, you would start the expression with the array sigil@
.) - 要在Perl中通过索引获取单个数组元素,语法为$ a [$ i],而不是@a [$ i]。因为你只需要一个标量值,所以表达式必须以标量符号$开头。 (如果您需要表达式中的值列表,则可以使用数组sigil @启动表达式。)
-
push
modifies the array given by the first argument, so there's no need to assign the result back to the array in the expression. - push修改第一个参数给出的数组,因此不需要将结果分配回表达式中的数组。
- You are missing a closing parenthesis in your
push
expression. - 您在推送表达式中缺少右括号。
- In your same code, you have
@new
and@array
, and you are only adding elements from@a
and@s
(i.e. you forgot about@i
). - 在同一个代码中,你有@new和@array,而你只是添加来自@a和@s的元素(即你忘记了@i)。
- You are pushing elements onto the array, but you aren't concatenating them into the desired string format.
- 您正在将元素推送到数组上,但您没有将它们连接成所需的字符串格式。
Here is a working version of your implementation:
以下是您的实施的工作版本:
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;
(The //
means "defined-or".)
(//表示“已定义 - 或”。)
Here's how I might write it:
这是我写它的方式:
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";
(The $#a
means "give me the index of the last element of the array @a
.")
($#a表示“给我数组@a的最后一个元素的索引。”)
#4
-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);