【问题标题】:why pop/shift not work with map/grep in perl为什么 pop/shift 在 perl 中不能与 map/grep 一起使用
【发布时间】:2017-07-13 14:08:40
【问题描述】:

我想在mapgrep 操作之后获取第一个或最后一个元素 过阵列。将shiftpop 运算符与mapgrep 一起使用 似乎不起作用。有什么建议么?如果我从map 保存结果,它会起作用 进入数组变量并弹出它,但我想在一行中做到这一点。

:$ cat map.pl 
use strict;
use warnings;
my @arr = (1,2,3,4);
my $ele = pop ( map{10* $_ } @arr ) ;
print "\n element is $ele";
:$ perl map.pl
Not an ARRAY reference at map.pl line 4.

【问题讨论】:

  • 在列表上下文中,mapgrep 生成列表,但 shift/unshiftpush/pop 对数组进行操作。列表和数组在 Perl 中不是一回事。您应该不太担心试图在一行中完成所有事情,而应该更担心编写正确的代码。
  • @MattJacob 我认为这是对这个问题的一个很好的回答
  • 来自 Matt Jacob 的(很好但已删除?)答案的一个很好的链接:list vs array

标签: perl


【解决方案1】:
map{10* $_ } @arr

产生一个列表,其元素是@arr 的对应元素乘以10。它生成数组。因此,你不能pop 任何东西。您可以访问最后一个元素:

(map 10 * $_, @arr)[-1]

但是,地图不会改变@arr。如果你想这样做,

 $_ *= 10 for @arr;

map更合适。

【讨论】:

    【解决方案2】:

    shiftpop 的第一个参数必须是数组(@NAME@BLOCK),而不是 mapgrep 运算符(与数组无关)。

    您可以构建一个数组,从该数组到 shift/pop

    my $first_ele = shift @{ [ map { 10 * $_ } @arr ] };           # If you want first
    my $last_ele  = pop   @{ [ map { 10 * $_ } @arr ] };           # If you want last
    

    但这很浪费。您可以通过使用列表分配或列表切片来避免创建数组。

    my ($first_ele) = map { 10 * $_ } @arr;                        # If you want first
    my $first_ele = ( map { 10 * $_ } @arr )[0];                   # If you want first
    my $last_ele  = ( map { 10 * $_ } @arr )[-1];                  # If you want last
    my ($first_ele, $last_ele) = ( map { 10 * $_ } @arr )[0, -1];  # If you want both
    

    但这仍然是浪费。当您只想要最后一个的乘积时,无需将所有元素相乘。以下更有意义:

    my $first_ele = 10 * $arr[0];                                  # If you want first
    my $last_ele  = 10 * $arr[-1];                                 # If you want last
    my ($first_ele, $last_ele) = map { 10 * $_ } @arr[0, -1];      # If you want both
    

    【讨论】:

      【解决方案3】:

      在列表上下文中,mapgrep 生成列表,但 shift/unshiftpush/pop 对数组进行操作。 Lists and arrays are not the same thing in Perl。您应该不太担心尝试在一行中完成所有操作,而应该更担心编写正确的代码。

      【讨论】:

        【解决方案4】:

        第一个还是最后一个?首先你可以使用

            use strict;
            use warnings;
            my @arr = (1,2,3,4);
            my ($ele) = map{10* $_ } @arr;
            print "\n element is $ele\n\n";
        

        【讨论】:

        • 似乎 OP 希望能够同时做到这两点,因为他们提到了第一个和最后一个,以及 shift 和 pop。我调整了 OP 以明确这一点。
        猜你喜欢
        • 2011-09-23
        • 2021-12-06
        • 1970-01-01
        • 1970-01-01
        • 2013-02-09
        • 2014-02-18
        • 1970-01-01
        • 2011-03-24
        • 1970-01-01
        相关资源
        最近更新 更多