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

I have a hash to be sorted on the number of letter 'd' present in the value. My code to do the same is like this:

%hash = sort {scalar (split ("d",$a)) <=> scalar (split ("d",$b)) } (keys (%hash))

But it gives error saying use of implicit split to @_ is deprecated.

Replies are listed 'Best First'.
Re: Sorting a hash in one line
by davido (Cardinal) on Jun 21, 2010 at 07:02 UTC

    Plain old hashes can't be sorted. If you want to maintain some order, keep track of the keys in an array, and get them into whatever sorted order you wish.

    Reading your code from left to right, "%hash = sort" is your first problem.


    Dave

Re: Sorting a hash in one line
by LanX (Saint) on Jun 21, 2010 at 07:21 UTC
    normal hashes have no order and can't be sorted!

    But if you wanna get the values in a special order you can use a hashslice on sorted keys in one line

    @svalues = @hash{ sort {...} keys %hash }

    > But it gives error saying use of implicit split to @_ is deprecated.

    scalar split has the ugly side effect to globber @_ (AFAIK at least prior 5.12), you may try something like m/(d)/ or tr/d// to count the "d"s.

    UPDATE:

    @svalues = @hash{ sort { $a=~tr/d// <=> $b=~tr/d// } keys %hash } should do.

    even @svalues = @hash{ sort { $a=~tr/d// <=> $b=~tr/d// } %hash } does what you want (but I can't remember where it's documented) (was wrong)

    Cheers Rolf

    UPDATE: corrected typo, thx to davido

      Sorting the list returned by %hash is quite wrong.

      use strict; use warnings; my %hash = map { $_ => 1 } qw( foo food dood ); my @svalues1 = @hash{ sort { $a=~tr/d// <=> $b=~tr/d// } keys %hash }; my @svalues2 = @hash{ sort { $a=~tr/d// <=> $b=~tr/d// } %hash }; print(0+@svalues1, "\n"); # 3 print(0+@svalues2, "\n"); # 6
      A reply falls below the community's threshold of quality. You may see it by logging in.

      Just a nit... but I would think "@svals" would be a more appropriate name for a variable holding values spit out from a hash slice, than "@skeys."


      Dave

Re: Sorting a hash in one line
by ikegami (Patriarch) on Jun 21, 2010 at 07:56 UTC

    I answered this in the CB when you asked there. Here it is again since you asked again.

    • You're assigning a list of keys to a hash when it takes a list of key-value pairs.

    • You assume the order of the key-value pairs you assign to a hash matters, but it doesn't.

    • As for the waning, it says you shouldn't use split to assign to @_. That's particularly true here since you don't want to assign to @_. (See the docs.) You can use $s=~tr/d// to count the number of instances of "d". You could also use (()=$s=~/d/g).

    my @sorted_keys = sort { $a=~tr/d// <=> $b=~tr/d// } keys(%hash);
Re: Sorting a hash in one line
by jau (Hermit) on Jun 21, 2010 at 09:34 UTC
      Since nobody mentioned it yet

      Well I linked to another thread mentioning tie mechanisms and Tie::IxHash ;-))

      Seriously, it's such a regular (and boring) FAQ that one could consider text mining mechanisms on the post's text to generate an automated answer or intercept the preview before posting ...

      perldoc -q hash sorted already helps...

      Cheers Rolf

Re: Sorting a hash in one line
by Anonymous Monk on Jun 21, 2010 at 14:21 UTC

    Don't try to write things in one line until you first understand what you are doing in long form.