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

I have a hash of hashes that I maintain in a module that lives within a software configuration management system (ClearCase, but that is of no real import). I use the hash as a simple statistics database. A statistics collection and publishing script...

  1. uses the module
  2. updates the (in memory) hash with new statistics
  3. publishes the new statistics to some webpage
  4. checksout the module file from software CM
  5. stringifies the hash with Data::Dumper (Purity => 1)
  6. re-writes the module file using the stringified hash
  7. checksin the modified module file

What I (think I) want is to tie *all* the hashes in the hash of hashes so that they are always retrieved sorted, so that the output from Data::Dumper is always consistent. This would, I believe, allow the output of a diff against the previous version of a module file to consistently report accurate results.

Is there any easy way to declare that all the nested hashes in a structure will be sorted? BTW, I don't care one whit about the sort comparison subs - I just want consistency in the output. I am not that familiar with this kind of problem (nor really deeply with ties). Please also note that I do want to continue to maintain the hash as an entity declared and defined purely by the text within the module, if possible. I don't want to serialize it via some external database (using Storable or some such), since doing so would prevent module version diffs from being useful.

One other question - upon an eval of the stringified (by Data::Dumper) hash will the hashes be re-tied automagically or do I have to handle that myself somehow?

Conceptual guidance will be very appreciated. I can probably figure a reasonably acceptable approach myself, but I'd like to know the best and easiest way to do this.

Replies are listed 'Best First'.
Re: Sort-Tying all hashes in a hash of hashes
by tcf22 (Priest) on Sep 10, 2003 at 18:41 UTC
    You can use Tie::Hash::Array to ensure that a hash is sorted.
    Added:
    Limbic~Region brought up that you need a hash of hashes sorted. Here is a simple example of how to use this with Data::Dumper.
    use Tie::Hash::Array; tie my %hash, 'Tie::Hash::Array'; foreach(a..z){ tie my %tmp, 'Tie::Hash::Array'; my $t = $_; foreach my $i(0..5){ $t++; $tmp{$t} = $i; } $hash{$_} = \%tmp; } use Data::Dumper; print Dumper \%hash; untie %hash; __OUTPUT__ $VAR1 = { 'a' => { 'b' => 0, 'c' => 1, 'd' => 2, 'e' => 3, 'f' => 4, 'g' => 5 }, 'b' => { 'c' => 0, 'd' => 1, 'e' => 2, 'f' => 3, 'g' => 4, 'h' => 5 }, 'c' => { 'd' => 0, 'e' => 1, 'f' => 2, 'g' => 3, 'h' => 4, 'i' => 5 }, 'd' => { 'e' => 0, 'f' => 1, 'g' => 2, 'h' => 3, 'i' => 4, 'j' => 5 }, 'e' => { 'f' => 0, 'g' => 1, 'h' => 2, 'i' => 3, 'j' => 4, 'k' => 5 }, 'f' => { 'g' => 0, 'h' => 1, 'i' => 2, 'j' => 3, 'k' => 4, 'l' => 5 }, 'g' => { 'h' => 0, 'i' => 1, 'j' => 2, 'k' => 3, 'l' => 4, 'm' => 5 }, 'h' => { 'i' => 0, 'j' => 1, 'k' => 2, 'l' => 3, 'm' => 4, 'n' => 5 }, 'i' => { 'j' => 0, 'k' => 1, 'l' => 2, 'm' => 3, 'n' => 4, 'o' => 5 }, 'j' => { 'k' => 0, 'l' => 1, 'm' => 2, 'n' => 3, 'o' => 4, 'p' => 5 }, ....

    - Tom

Re: Sort-Tying all hashes in a hash of hashes
by demerphq (Chancellor) on Sep 10, 2003 at 19:29 UTC

    What I (think I) want is to tie *all* the hashes in the hash of hashes so that they are always retrieved sorted, so that the output from Data::Dumper is always consistent.

    This is overkill of a level that boggles my mind. You can either upgrade Data::Dumper so you can use the Sorted Sortkeys method available in later releases, or do some minor surgery to Data::Dumper itself (dont forget to rename it so you dont accidentally overwrite it or something) and leave it at that. Doing this via a Tie is going to be Very Hard, hacking dumper to produce sorted output is so close to trivial Ill just leave it at that.


    ---
    demerphq

    <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...

    • Update:  
    Fixed the method name.


Re: Sort-Tying all hashes in a hash of hashes
by Limbic~Region (Chancellor) on Sep 10, 2003 at 18:43 UTC
    welchavw,
    To my knowledge, no module exists that maintains sort order of a HoH at all levels. One way to do it would be to tie each hash seperately using Tie::IxHash or Tie::Hash::Array, then construct your final tied HoH. They probably has the functionality you are looking for, but it will be a pain to tie all levels.

    I don't know if you can overload keys, but that might be the way to go.

    <plug>
    If your needs change, and you are looking for something more robust in maintaining sorted order, you can look for Tie::Hash::Sorted when it is released in the next few days. In the interim, you can read about it here and here.
    </plug>

    Cheers - L~R

Re: Sort-Tying all hashes in a hash of hashes
by welchavw (Pilgrim) on Sep 10, 2003 at 20:17 UTC

    Thanks to all who have provided replies, they're all helpful. The approaches described are about what I thought I might have to do to get this working. It is, however, exceedingly helpful to know that loops will be required to build such data structures (or else mods to the dumping code) and that more magical ways have not been invented for this kind of problem.

    ,welchavw