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

Hi Brethren,
I am trying to sort three hashes the contents of which are show below, they are linked by a common key or value in each hash. i.e
Hash A% key (score) Value (text) 62 accord newton second 78 acceler smaller greater 56 addit law motion Hash B% key (text) Value (line number) addit law motion 12 accord newton second 19 acceler smaller greater 9 Hash C% key (text) Value (line number) According to newton 19 The acceleration is 9 In addition to his laws 12
The contents of Hash “A” (value) match the contents of Hash “B” (key) not necessarily on the same line.
The contents of Hash “B” (value) match the contents of Hash “C” (value) again not necessarily on the same line.
So there is a common link between all hashes like a relational database.

I would like to sort Hash “A” (key) in descending order and then align the (value) Hash “A” with Hash “B” (key).
Then use that sort, to align Hash “C” so that the key value pairs of "C" can be printed out in the same order as the sorted “A” Hash.

Any help would be much appreciated.

Replies are listed 'Best First'.
Re: Sorting or Aligning Parallel Hashes
by ikegami (Patriarch) on Mar 28, 2006 at 18:02 UTC

    Your analysis of the problem is quite accurate. If you do those steps, one at a time, you get what you want. Keep in mind that hashes can't be sorted, just their keys and/or values.

    I would like to sort Hash “A” (key) in descending order
    my @sorted_scores = sort { $b <=> $a } keys %HashA;
    and then align the (value) Hash “A” with Hash “B” (key).
    my @sorted_words = map { $HashA{$_} } @sorted_scores;
    Then use that sort, to align Hash “C” so that the key value pairs of "C" can be printed out in the same order as the sorted “A” Hash.
    my @sorted_line_nums = map { $HashB{$_} } @sorted_words;

    And the print:

    print($HashC{$_}, "\n"); foreach @sorted_line_nums;

    All together now:

    print("$_\n"); foreach map { $HashC{$HashB{$HashA{$_}}} } sort { $b <=> $a } keys %HashA;

    I'm curious as to how you handle two lines having the same score, if the score is the key.

      Thanks very much for the help.
      Could you explain further how to use the sorted hash "A" to align the second hash "B"

        There's no such thing as a sorted hash(*), and I don't know what kind of terminology "align" is. You're confusing yourself by trying to be technical. Your data does NOT consist of unsorted hashes, sorted hashes and alignments; your data consists of scores, keywords, line numbers, text and the relationships between them.

        Your question is then "Could you explain further how to get the keywords for a list of (sorted) scores?" I used:

        my @sorted_words = map { $HashA{$_} } @sorted_scores;
        I could also have used:
        my @sorted_words; foreach (@sorted_scores) { push(@sorted_words, $HashA{$_}; }

        %HashA defines the relationship between scores and keywords. To get a list of keywords for a list of scores, simply loop over all the scores and use %HashA to find the corresponding keywords.

        * - Well, it's possible using tie, but that's neither needed nor relevant here.

Re: Sorting or Aligning Parallel Hashes
by Tanktalus (Canon) on Mar 28, 2006 at 17:58 UTC

    To be honest, that doesn't seem too bad - what have you tried?

    Hint: you'll want intermediate arrays to keep track of the sort order.