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

时间:2010-01-05 14:17:05

标签: perl arrays reference

我有这个例子:

my $numbers = [ 1, 2, 3, 4, 5, 6 ];
my $newarray = [ reverse @$numbers ];

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

my $newarray = reverse $numbers;

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

)8936f22x0(YARRA

有没有更好的方法在Perl 中反转arrayref而不更改第一行

更新

my $mails = [ reverse @{$mail_api->GetLogSendMail({ customer_id => $id })} ];

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

6 个答案:

答案 0 :(得分:9)

如果你可以使用数组而不是arrayref,那么试试这个:

my @newarray = reverse @$numbers;

代码my $newarray = reverse $numbers无效,因为在标量上下文中调用了reverse,这使得它返回一个字符串,其字符的顺序相反。来自reverse manual

  

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

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

## declare $newarray somewhere else
@$newarray = reverse @$numbers;

<强>更新

可能您想创建自己的功能:

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

答案 1 :(得分:7)

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

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

use autobox;
my $arr = [ 1 .. 10 ];
$arr->reverse;

只是为了跟进,为什么我们有匿名数组语法的真正原因是创建深层结构并避免传递数组(需要将它们推入堆栈),而不是创建那些应该是array-arrays数组。

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

答案 2 :(得分:6)

你有几种选择。

不要试图把它全部塞进一行:

my $mails = [ reverse @{$mail_api->GetLogSendMail({ customer_id => $id })} ];

变为:

my $mails = $mail_api->GetLogSendMail({ customer_id => $id });
@$mails = reverse @$mails;

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

my $inviolate_mails = $mail_api->GetLogSendMail({ customer_id => $id });
my $mails;  @$mails = reverse @$inviolate_mails;

要将所有内容保存在一行上,请使用Ivan Nevostruev建议的子程序:

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

my $mails = reverse_ref $mail_api->GetLogSendMail({ customer_id => $id });

如果你需要在数组引用上加载list-ops,可以考虑创建一个库:

package ArrayRef::Util;
# boiler plate skipped.

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

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

# and so on

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

use autobox;

my $mails = [ $mail_api->GetLogSendMail({ customer_id => $id })->reverse ];

有关autobox的更多信息,请参阅Should I use autobox in Perl?

答案 3 :(得分:2)

你有没有找到这样的东西:

#!/usr/bin/perl

$myNames = ['Jacob', 'Michael', 'Ethan', 'Andrew'];
@reversedNames = reverse(@$myNames); 

print @reversedNames;

查看this教程。

答案 4 :(得分:0)

我不知道您是否可以控制原始对象的来源,但如果您这样做,那么将->reverse方法添加到该包中会怎么样?

my $mails = $mail_api->GetLogSendMail({ customer_id => $id })->reverse;

答案 5 :(得分:0)

两个问题:

  1. 您对$mail_api的任何对象有多少控制权?
  2. 您真的需要$mails作为参考而不是实际数组吗?为什么会这样?
  3. 如果1的答案是“some”而2是“no”,则更改GetLogSendMail方法以返回列表而不是数组引用。然后你的代码变得简单

    my @mails = reverse $mail_api->GetLogSendMail({ customer_id => $id });