laziness, impatience, and hubris PerlMonks

How to Sort a Hash According to the Keys in the Hash

by ishootperls (Novice)
 on Dec 02, 2015 at 18:31 UTC Need Help??

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

Mornin' Monks !! I come to seek wisdom. I've tried a few different ways to sort a hash table according to the keys in the hash. What I mean specifically is this, If I enter the Keys of my hash like so, they should print out like so:

```my %newHoA   = (
"Books"     =>  ["Cannery Row", "Animal Farm", "East of Eden"],
"Places"    =>  ["BigSur","Zion", "CrateLake"] );

foreach my \$keyHoA (<sort goes here> keys %newHoA) {

print "The key is: \$keyHoA" . " And one value is: \$newHoA{\$req}[0]" .
+ "\n";

}

So the output should be something like:

```The key is: Sports And the value is: Soccer
The key is: Books And the value is: Cannery Row
The key is: Places And the value is: BigSur
Well, I hope some monk out there has the wisdom I seek. Thanks.

UPDATE:
Thank you all for the suggestions. Its helpful to get different perspectives on a single problem.

"An incendiary Perl will solve that problem" :-) - myself

Replies are listed 'Best First'.
Re: How to Sort a Hash According to the Keys in the Hash
by choroba (Cardinal) on Dec 02, 2015 at 18:44 UTC
You can't retrieve the order of the keys from a normal hash. It's too late - the hash is already unsorted.

However, you can use Tie::IxHash:

```use Tie::IxHash;

tie my %h, 'Tie::IxHash';
%h = ( Sports =>  ["Soccer","UltimateFrisbee","Basketball"],
Books  =>  ["Cannery Row", "Animal Farm", "East of Eden"],
Places =>  ["BigSur","Zion", "CrateLake"] );

print "\$_\n" for keys %h;
```(\$q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+\$1,++print+eval\$q,q,a,

Outstanding !! Wasn't aware of such module. Thanks choroba !!

"An incendiary Perl will solve that problem" :-) - myself
Re: How to Sort a Hash According to the Keys in the Hash
by NetWallah (Canon) on Dec 02, 2015 at 21:21 UTC
See also : Hash::Ordered , a newer, pure perl implementation.

"Hash::Ordered attempts to find the sweet spot with simple implementation, reasonably good efficiency for most common operations, and a rich, intuitive API."

The documentation includes a discussion comparing various implementations of this feature.

Our business is run on trust. We trust you will pay in advance.

Re: How to Sort a Hash According to the Keys in the Hash
by neilwatson (Priest) on Dec 02, 2015 at 18:48 UTC
... sort keys %my_hash ...

My first thought too, but ishootperls seems to want to recover the insertion order of the keys into the hash, which, per choroba above, is available through something like Tie::IxHash.

Give a man a fish:  <%-{-{-{-<

..or by hardcoding the order into an array and use this array to generate the hash:
```my @order = qw(Sports Books Places);
my %hash;
# populate the hash's slice
@hash{@order} = ( # we need a list
# of three anonymous array
["Cannery Row", "Animal Farm", "East of Eden"],
["BigSur","Zion", "CrateLake"]
);

#retrieve them in the desired @order
print map { "\$_ => ".(join ',',@{\$hash{\$_}})."\n" } @order ;

array are good to have things ordered, queue and series
hashes are better to count things or have list of uniques, or general associations.

sort can accept a block of code to do your custom sort but is impossible for sort to know a priori the order followed while inserting values, because hashes are unsorted, by definition.

L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

No, you misunderstood him (or he misunderstood you :) sort is applied to the list of of keys returned by keys (the keys returns list in random order). So your foreach loop shall iterate over sorted list of keys. You then use current key to obtain value from hash. If you shall access your hash only ones, then you can use this approach. If there are multiple accesses, then it makes sense to keep sorted list of keys to avoid sorting multiple times.

On a side note. Your code in the original message contains error. You use variable \$keyHoA as iterator of the loop, but to access value of the hash inside of the loop you use variable \$req (\$newHoA{\$req}[0])

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1149197]
Approved by toolic
Front-paged by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2023-02-09 05:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
I prefer not to run the latest version of Perl because:

Results (44 votes). Check out past polls.

Notices?