我有这个例子:
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 })} ];
我们的想法是让上面的代码更好。
答案 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
中,reverse
,pop/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)
两个问题:
$mail_api
的任何对象有多少控制权?$mails
作为参考而不是实际数组吗?为什么会这样?如果1的答案是“some”而2是“no”,则更改GetLogSendMail
方法以返回列表而不是数组引用。然后你的代码变得简单
my @mails = reverse $mail_api->GetLogSendMail({ customer_id => $id });