Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Sorting an hash array

by kepler (Scribe)
on Jul 25, 2014 at 22:45 UTC ( #1095109=perlquestion: print w/replies, xml ) Need Help??
kepler has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to sort an hash array alphabetically. Here's what I'm doing:
my @keys = sort { $functions{$a} <=> $functions{$b} } keys(%functions) +; my @vals = @functions{@keys}; $info = "out.txt"; open(out,">$info"); print out "Key: $_ and Value: $functions{$_}\n" foreach (keys%function +s); close;
but I'm getting the wrong results... Any idea why? Kind regards, Kepler

Replies are listed 'Best First'.
Re: Sorting an hash array
by AppleFritter (Vicar) on Jul 25, 2014 at 22:56 UTC

    Two things.

    1. <=> is for numerical comparison; you want the cmp operator instead. See Equality Operators.
    2. Although you're sorting your hash keys, you're not actually doing anything with them, and when you're outputting to your file, you're going through them in their natural (read: random) order again.

    Remember, you cannot sort a hash as such. You can take its keys and sort them as a list, but the hash itself does not have any specific order to it; there is no concept of "the first key", "the second key" and so on. All the keys are created equal, as it were; none takes precedence over any other.

    (Side note: of course functions such as keys, values or each will iterate through a hash in a certain order, by necessity, but this order is essentially random, and code that relies on any specific order there is broken, even if the order happens to be reproducible.)

    Anyhow, getting back to your question, try this:

    use feature qw/say/; ... my $info = "out.txt"; open my $out, ">", $info or die "Cannot open file for writing: $!"; say $out "Key: $_ and Value: $functions{$_}" foreach (sort { $function +s{$a} cmp $functions{$b} } keys %functions); close $out or die "Cannot close file: $!";

    I've also taken the liberty of making a other few changes to your code, namely:

    1. Using lexical filehandles.
    2. Using the three-argument form of open.
    3. Error-checking.
    4. Using say when you want a trailing newline.

    They're not the law, but they're good ideas anyway. ;)

      If execution time is important and the number of items being sorted is large enough or the calculation per item is expensive enough it is worth caching each calculated sort value. The classic pattern for that is:

      my @sortedKeys = map {$_->[1]} sort {$a->[0] cmp $b->[0]} map {[function($_), $_]} keys %hash;

      which generates then sorts a list of sort_value, key_value pairs and returns the sorted keys.

      Perl is the programming world's equivalent of English
      Hi, I've tryed the code you gave me: same disorded result.... Regards, Kepler

        I don't see offhand what would be wrong with AppleFritter's code, but here's some code closer to your OP, at least as regards sorting. Critically, IMHO, this code includes example data. Can you say where the 'disorder' creeps in? (In particular, since the sort comparison in AppleFritter's code is lexic versus numeric in the original, how can it be the same disorder?)

        c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my %funcs = qw(1 a 2 aa 3 aaa 4 z 5 zz 6 b 7 bb); dd \%funcs; ;; my @sorted_keys = sort { $funcs{$a} cmp $funcs{$b} } keys %funcs; dd \@sorted_keys; ;; my @sorted_vals = @funcs{@sorted_keys}; dd \@sorted_vals; ;; print qq{'$_' -> '$funcs{$_}'} for @sorted_keys; " { 1 => "a", 2 => "aa", 3 => "aaa", 4 => "z", 5 => "zz", 6 => "b", 7 => + "bb" } [1, 2, 3, 6, 7, 4, 5] ["a", "aa", "aaa", "b", "bb", "z", "zz"] '1' -> 'a' '2' -> 'aa' '3' -> 'aaa' '6' -> 'b' '7' -> 'bb' '4' -> 'z' '5' -> 'zz'

        Did you understand that AppleFritters code does not (and cannot) fix the hash - only the output?
Re: Sorting an hash array
by Laurent_R (Canon) on Jul 27, 2014 at 10:57 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1095109]
Approved by AppleFritter
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2019-01-23 15:24 GMT
Find Nodes?
    Voting Booth?
    After Perl5, I'm mostly interested in:

    Results (407 votes). Check out past polls.