Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Why dosen't it work ?
shift (sort ( @array ) );
Doing
@array = sort @array; shift @array;
is OK but down right un-perlish

By the way, I'm not really trying to get the min value of the array. I really just want to shorten the array, ala;

if (@$array[$_] == $number) { @$array[$_] = 0; @array = (sort {$a <=> $b} (@$array)); shift; }
Something tells me there is a better way. Any suggestions?

Replies are listed 'Best First'.
Re: Type of arg 1 to shift must be array (not sort)
by philcrow (Priest) on Dec 15, 2005 at 20:34 UTC
    Sort returns a list. Lists are immutable. Shift modifies its array argument. These can't mix. You must store the result in an array or shift can't work on it.

    Phil

Re: Type of arg 1 to shift must be array (not sort)
by eff_i_g (Curate) on Dec 15, 2005 at 21:06 UTC
    perl-ish:
    #!/usr/bin/perl -w use strict; my @array = qw( b d c a e g f ); print shift @{[ sort @array ]};
      Note that this is true with a number of other different perlfuncs that return as immutable lists rather than arrays... copying the de-referenced return and forcing it back into an array will cure most non-perlish headaches.

      For example:
      #!/usr/bin/perl use strict; use warnings; my @array = qw( a b c d e f ); # With sort.. my $sorted = shift( @{ [ sort( @array ) ] } ); # With grep my $grepped = shift( @{ [ grep{ /\w+/ } @array ] } ); # With map my $mapped = shift( @{ [ map{ $_ } @array ] } ); # As a stringified method call my $method = "@{ [ FooBar->new()->a_method() ] }"; print "$sorted\n$grepped\n$mapped\n$method\n"; package FooBar; use strict; use warnings; sub new { return bless {}, shift; } sub a_method{ return 'some string'; }
      Yay for Perl!

      ---hA||ta----
      print map{$_.' '}grep{/\w+/}@{[reverse(qw{Perl Code})]} or die while ( 'trying' );
        I don't know why you'd waste the time and space to array-ify the return value when a literal slice will work just as easily for those. Instead of:
        my $result = shift @{[some list function]};
        just write
        my $result = (some list function)[0];
        A whole lot easier on the CPU and the eyes. That's why I invented the literal slice (one of the few things I can lay direct claim to in Perl).

        Of course, if you're going to store it into a scalar like this, you can simplify it further:

        my ($result) = some list function;

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

      similar to my first thought which was:
      perl -le '@x=(9,8,4,3,6,5); print ((sort @x)[0])'
      BUT not what OP wanted .. he wants @array to contain N-1 values at the end.. Something like (though not the most efficent):
      perl -le '@x=(9,8,4,3,6,5); print join ":", ((sort @x)[1..$#x])' # OP: @array = sort @array; shift @array; #using above: @array = ((sort @array)[1..$#array])
Re: Type of arg 1 to shift must be array (not sort)
by Roy Johnson (Monsignor) on Dec 15, 2005 at 21:31 UTC
    I think splice is what you're looking for:
    if ($array->[$_] == $number) { splice(@$array, $_, 1); }

    Caution: Contents may have been coded under pressure.

      But be careful using splice on any part of a LIST that you're iterating over with foreach.

      If any part of LIST is an array, foreach will get very confused if you add or remove elements within the loop body, for example with splice. So don't do that.
Re: Type of arg 1 to shift must be array (not sort)
by ikegami (Patriarch) on Dec 15, 2005 at 21:28 UTC
Re: Type of arg 1 to shift must be array (not sort)
by sauoq (Abbot) on Dec 16, 2005 at 04:33 UTC
    Something tells me there is a better way. Any suggestions?

    do {(my $t,@a) = sort @a};

    Update: Use tinita's suggestion below. It's the idiom I had in mind anyway; I guess I just didn't recall it correctly.

    -sauoq
    "My two cents aren't worth a dime.";
      (undef, @a) = sort @a;