如何反转数组引用并将其存储在Perl中的另一个数组引用中?

Pet*_*and 2 arrays perl reference

我有这个例子:

my $numbers = [ 1, 2, 3, 4, 5, 6 ];
my $newarray = [ reverse @$numbers ];
Run Code Online (Sandbox Code Playgroud)

此示例包含一些合成代码,以使$numbersarrayref适合该reverse函数.我想删除该代码并执行更多类似的操作:

my $newarray = reverse $numbers;
Run Code Online (Sandbox Code Playgroud)

我知道这不起作用,它返回:

)8936f22x0(YARRA
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法在不更改第一行的情况下在Perl中反转arrayref ?

更新:

my $mails = [ reverse @{$mail_api->GetLogSendMail({ customer_id => $id })} ];
Run Code Online (Sandbox Code Playgroud)

我们的想法是让上面的代码更好.

Iva*_*uev 9

如果您可以使用array而不是arrayref,那么试试这个:

my @newarray = reverse @$numbers;
Run Code Online (Sandbox Code Playgroud)

代码my $newarray = reverse $numbers无效,因为reverse标量上下文中调用,这使得它以相反的顺序返回字符串.来自reverse手册:

在标量上下文中,连接LIST的元素并返回一个字符串值,其中所有字符的顺序相反.

如果在上面的某处声明$ newarray变量,可以按以下方式编写它:

## declare $newarray somewhere else
@$newarray = reverse @$numbers;
Run Code Online (Sandbox Code Playgroud)

更新

可能是你想创建自己的功能:

sub reverse_by_ref {
    return [ reverse @{$_[0]} ];
}
Run Code Online (Sandbox Code Playgroud)


Eva*_*oll 7

我认为这里真正的基本问题是你存储$numbers为array-ref并尝试将它们作为数组进行操作.这可能是常见的,但不正确.人们这样做是为了使数组始终保持参考形式,但正确的方法是使用原生结构而不是对它的引用.在参考形式scalarreverse,pop/push/shift/unshift和所有其他人将需要明确的参与来操作阵列.这对于允许引用数组的所有语言都是通用的 - 查看C的字符指针与字符数组以及sizeof()运算符之类的内容.我们在这里真正做的是利用perl非常方便的匿名数组语法来弥补自己的不利.

这不是一个真正的问题,但是取消引用的微小开销和差异的几乎不​​可避免的视觉元素.现在继续到/右/回答.有一个现代化的解决方案,它与之相伴autobox.Autobox提供包含类似对象语法的所有类型引用.

use autobox;
my $arr = [ 1 .. 10 ];
$arr->reverse;
Run Code Online (Sandbox Code Playgroud)

只是跟进,真正的原因,为什么我们有匿名数组的语法是创建与深层结构,避免将阵列(需要将它们推到堆栈),远远超过创造的东西,应该是数组作为阵列的裁判.

  • $foo( [1..100] ) 比...快得多 $foo( 1..100 )
  • $arr[1] = [1,2,3] 比方便更方便 @temp = 1,2,3; $arr[1] = \@temp


dao*_*oad 6

你有几个选择.

不要试图在一条线上塞满所有东西:

my $mails = [ reverse @{$mail_api->GetLogSendMail({ customer_id => $id })} ];
Run Code Online (Sandbox Code Playgroud)

变为:

my $mails = $mail_api->GetLogSendMail({ customer_id => $id });
@$mails = reverse @$mails;
Run Code Online (Sandbox Code Playgroud)

如果GetLogSendMail愚蠢到返回对你不应该搞乱的数组的引用,那么你将不得不稍微修改它以创建一个新数组:

my $inviolate_mails = $mail_api->GetLogSendMail({ customer_id => $id });
my $mails;  @$mails = reverse @$inviolate_mails;
Run Code Online (Sandbox Code Playgroud)

为了将所有内容保持在一行,请使用Ivan Nevostruev建议的子程序:

sub reverse_ref \@ {
    return [ reverse @{$_[0]} ];
}

my $mails = reverse_ref $mail_api->GetLogSendMail({ customer_id => $id });
Run Code Online (Sandbox Code Playgroud)

如果您需要在数组引用上执行大量列表操作,请考虑创建一个库:

package ArrayRef::Util;
# boiler plate skipped.

sub reverse_ref \@ {
    return [ reverse @{$_[0]} ];
}

sub push_ref \@\@ {
    push @{$_[0]}, @{$_[1]};
}

# and so on
Run Code Online (Sandbox Code Playgroud)

最后,Evan Carroll的autobox建议也有帮助:

use autobox;

my $mails = [ $mail_api->GetLogSendMail({ customer_id => $id })->reverse ];
Run Code Online (Sandbox Code Playgroud)

请参阅我应该在Perl中使用autobox吗?有关autobox的更多信息.