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

Hi all,
I would like to sort "$hash_value" based on year in that structure. I am getting year in sorted in ascending format in another array and try to build new hash to represent new structure. But its not working. Please help me.
$hash_value = { '75.34.42.17511726663' => { '2005' => [ '11.5', '363,8 +42' ], '1995' => [ '', '200,000' ], '2004' => [ '9.2', '326,345' ], ' +2001' => [ '6.7', '263,645' ], '1995' => ['','200,000'],'1997' => [ ' +2.6', '212,118' ], '1998' => [ '3.7', '219,980' ], '2002' => [ '7.6', + '283,665' ], '2006' => [ '9.4', '398,148' ], '2000' => [ '7.7', '247 +,015' ], '1996' => [ '3.3', '206,680' ], '1999' => [ '4.2', '229,281' + ], '2003' => [ '5.4', '298,857' ] } }; # To sort year from the hash - working properly @year= sort {$a cmp $b} keys(%{$hash_value->{'75.34.42.17511726663'}}) +; # To build new structure - year ascending order format. It's not worki +ng $hash_result = {}; foreach $key (@year) { $hash_result->{'75.34.42.17511726663'}->{$key} = $hash_value->{'75 +.34.42.17511726663'}->{$key}; } Is there anyother method to sort using same hash name?

Replies are listed 'Best First'.
Re: problem while sorting hash
by davorg (Chancellor) on Mar 20, 2007 at 16:46 UTC

    You aren't creating a sorted hash. There is no such thing as a sorted hash (well, unless you use something like Tie::IxHash).

    Hashes are by nature unordered. All you are doing here is adding keys to a hash. You're adding them in the correct order, but they are stored in a (seemingly) random order.

    If you want things stored in a fixed order, then use an array. Not a hash.

    --

    See the Copyright notice on my home node.

    "The first rule of Perl club is you do not talk about Perl club." -- Chip Salzenberg

      davorg,
      There is no such thing as a sorted hash (well, unless you use something like Tie::IxHash).

      Minor nit: Tie::IxHash provides a facility to maintain insertion order. Any relationship of this order to a sorted list must be done by the user.* On the other hand, Tie::Hash::Sorted does provide a very flexible and relatively efficient way to keep your hash sorted regardless of hash modifications.

      I am not advocating using tied hashes without proper consideration but rather trying to clarify a common misconception about Tie::IxHash that others seem to have.

      Cheers - L~R

      It does provide methods to get the keys or values, normally returned by insertion order, in asciibetical order. This does not re-order the hash.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: problem while sorting hash
by wfsp (Abbot) on Mar 20, 2007 at 17:11 UTC
    To add to davorg's point about needing an array, here's one way you might do it.
    #!/usr/local/bin/perl use strict; use warnings; use Data::Dumper; $Data::Dumper::Indent = 1; my $hash_value = { '75.34.42.17511726663' => { '2005' => ['11.5', '363,842'], '1995' => ['', '200,000'], '2004' => ['9.2', '326,345'], '2001' => ['6.7', '263,645'], '1995' => ['','200,000'], '1997' => ['2.6', '212,118'], '1998' => ['3.7', '219,980'], '2002' => ['7.6', '283,665'], '2006' => ['9.4', '398,148'], '2000' => ['7.7', '247,015'], '1996' => ['3.3', '206,680'], '1999' => ['4.2', '229,281'], '2003' => ['5.4', '298,857'], } }; my $key = q{75.34.42.17511726663}; my @sorted_by_year; for my $year (sort keys %{$hash_value->{$key}}) { push @sorted_by_year, {$year => $hash_value->{$key}{$year}}; } print Dumper \@sorted_by_year;
    output:
      Thanks wfsp.
Re: problem while sorting hash
by TGI (Parson) on Mar 20, 2007 at 17:22 UTC

    Check out this brief article for inforomation and examples using tied hash modules that preserve ordering.

    Depending on your circumstances, it may be more expedient to save your @year array and use that anywhere you need to access your data in order.

    $hash_value = { '75.34.42.17511726663' => { # '1995' => [ '', '200,000' ], # Duplicate key, # overwritten by next line '1995' => [ '', '200,000' ], '1996' => [ '3.3', '206,680' ], '1997' => [ '2.6', '212,118' ], '1998' => [ '3.7', '219,980' ], '1999' => [ '4.2', '229,281' ], '2000' => [ '7.7', '247,015' ], '2001' => [ '6.7', '263,645' ], '2002' => [ '7.6', '283,665' ], '2003' => [ '5.4', '298,857' ], '2004' => [ '9.2', '326,345' ], '2005' => [ '11.5', '363,842' ], '2006' => [ '9.4', '398,148' ], } }; # To sort year from the hash @year= sort {$a cmp $b} keys(%{$hash_value->{'75.34.42.17511726663'}}) +; # To do stuff with structure - year ascending order format. my @foo_stuff; foreach $key (@year) { push @foo_stuff, Foo( $hash_value->{'75.34.42.17511726663'}{$key} +); } sub Foo { return @$_[0]; }

    In your code you have 1995 twice in your data set. Each key in a hash can only have one value, and only the last inserted value will be kept. If your data set will have multiple entries for each year, you'll need to reconsider your data structure.


    TGI says moo

      Thanks TGI.