【问题标题】:How can I reverse an array reference and store that in another array reference in Perl?如何反转数组引用并将其存储在 Perl 中的另一个数组引用中?
【发布时间】:2010-01-05 14:17:05
【问题描述】:

我有这个例子:

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 })} ];

想法是让上面这行代码更好。

【问题讨论】:

  • 你不喜欢[ reverse ...]的什么地方?
  • 如果你想让它更干净,请使用 Ivan Nevostruev 的建议。但老实说,你给出的线路并没有那么糟糕。我会担心别的事情。
  • @Chris 我认为你是对的。我希望有一个我忽略的解决方案。
  • 如果我必须反转存储在数组引用中的列表并将其存储在另一个数组引用中,我会做你所做的。除非您发现自己的情况存在重大问题,否则请继续生活。 :)
  • 没有重大问题 :) 我只是希望有更好的方法并对其他解决方案感到好奇。继续……

标签: perl arrays reference


【解决方案1】:

如果你可以使用 array 而不是 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]} ];
}

【讨论】:

  • 谢谢,不是我想要的,但它确实简化了一点。
  • 如果你把第二个建议全部写出来,将会产生更多的代码。
  • @kemp 一种反转数组引用的干净方法。
  • 您可能需要为此创建自己的函数(请参阅更新)。据我所知,没有内置函数可以通过引用来反转数组。
  • @Ivan 你的函数方法可能是最干净的方法,除了它需要一个额外的函数。
【解决方案2】:

我认为这里真正的根本问题是您将$numbers 存储为数组引用并尝试将它们作为数组进行操作。这可能是常见的地方,但它是不正确的。人们这样做是为了使数组始终保持引用形式,但正确的方法是使用本机结构而不是对其的引用。在引用形式scalarreversepop/push/shift/unshift 和所有其他形式中,都需要明确的尊重才能对数组进行操作。这对于所有允许引用数组的语言都很常见——看看 C 的字符指针与字符数组以及诸如 sizeof() 运算符之类的东西。实际上,我们在这里所做的是利用 perl 极其方便的匿名数组语法来损害您自己的利益。

这不是一个真正的问题,但是取消引用的开销很小,并且引用的视觉元素几乎不可避免。现在继续 /right/ 答案。对此有一个现代解决方案,它是autobox。 Autobox 提供了所有类型引用,包含在类似对象的语法中。

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

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

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

【讨论】:

    【解决方案3】:

    您有多种选择。

    不要试图将所有内容都塞进一行:

    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 });
    

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

    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 ];
    

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

    【讨论】:

      【解决方案4】:

      您是否在寻找类似的东西:

      #!/usr/bin/perl
      
      $myNames = ['Jacob', 'Michael', 'Ethan', 'Andrew'];
      @reversedNames = reverse(@$myNames); 
      
      print @reversedNames;
      

      看看this教程。

      【讨论】:

      • 对不起,不,我已经编写 perl 大约 10 年了。我正在寻找程序员的意见、知识和经验,而不是简单的答案。
      • 所以,不要抱歉。寻找你的答案。
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        两个问题:

        1. 您对$mail_api 的任何对象有多少控制权?
        2. 您真的需要$mails 作为引用而不是实际的数组吗?为什么会这样?

        如果 1 的答案是“一些”而 2 是“否”,则更改 GetLogSendMail 方法以返回列表而不是数组引用。然后你的代码就变得简单了

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

        【讨论】:

          猜你喜欢
          • 2018-10-19
          • 2020-08-06
          • 1970-01-01
          • 1970-01-01
          • 2014-05-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多