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

Dear monks

I want a subset of the keys I have in an hash. I tried the following:
splice( keys(%mh), 0, 100 ) ;
Which didn't work, it returned:
Type of arg 1 to splice must be array (not keys) at myprog.pl line 36, + near "100)" Compilation failed in require at ./test.pl line 8. BEGIN failed--compilation aborted at ./test.pl line 8.
I can fix this like
my @k = keys(%mh) ; splice( @k ...) ;
but I guess the one-liner should work too ?!
Any suggestions ?

cheers
LuCa

Update: thnx JavaFan, thats it, although I have doubts now about the order of keys :)

Replies are listed 'Best First'.
Re: Type of arg 1 to splice must be array (not keys)
by jwkrahn (Abbot) on Dec 14, 2009 at 12:57 UTC

    Try it using a list slice:

    my @k = ( keys %mh )[ 0 .. 99 ];
      Thats a good solution. The only problem is that I don't know the number of keys. So I can have more or less. Which means I have to rewrite your solution to
      my @k = (keys %mh)[0 .. (scalar keys(%my) <= 100 ? scalar keys(%mh) : +100)] ;
      Which doesn't look that good anymore. So I prefer 'splice'. Is there a way to convert this 'key' list into an array ?

        Your slice solution is buggy and uses scalar needlessly.

        my $keys = keys(%my) < 100 ? keys(%mh) : 100; my @k = ( keys %mh )[0..$keys-1];
        or
        my $keys = min 100, keys(%mh); my @k = ( keys %mh )[0..$keys-1];

        (List::Util provides min)

        A splice solution:

        my @k = keys %mh; splice( @k, 100 ) if @k > 100;

        You need the conditional to avoid the warning.

        Update: Added fix to OP's slice solution.

Re: Type of arg 1 to splice must be array (not keys)
by AnomalousMonk (Archbishop) on Dec 14, 2009 at 13:14 UTC

    I don't understand what you are trying to do. The statement
        splice( keys(%mh), 0, 100 ) ;
    suggests you want to remove the first 100 keys from the hash. However, a hash does not have a 'first n keys': 'first' implies order, and a hash does not have 'ordered' keys.

    The statement
        my @k = keys(%mh) ;
    gives you all the keys of the hash in essentially random order.

      I hope to get any order when I use Tie::IxHash I guess splice returns the removed elements, right ? So when I do something like
      ...... grep { ... } splice( keys(%my),0,100 ) ;
Re: Type of arg 1 to splice must be array (not keys)
by happy.barney (Friar) on Dec 14, 2009 at 15:31 UTC
    why splice ? :-)
    my $max = 100; my @list = grep $max-- > 0, keys %hash;
      If you format that like this:
       $max --> 0
      it looks like as if there was a "$max goes to zero" operator.

      A great way to confuse anybody who reads your code.
        Would you prefer --$max >= 0?