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

Got a hash like this

$hash = { k1 => [a1, b1, c1, d1], k2 => [a2, b2, c2, d1], k3 => [a3, b3, c3, d3] k4 => [a4, b4, c4, d3] } For the arrays where the d's are equal i want to do a numerical compar +ision on the a's and add a priority number at the end The output i expect $hash = { k1 => [a1, b1, c1, d1, 1], k2 => [a2, b2, c2, d1, 2], k3 => [a3, b3, c3, d3, 2] k4 => [a4, b4, c4, d3, 1] }

#basically for k1 and k2 the d's are equal and a1>a2 so i added 1 and 2 respectively at the end and a4>a3 etc. I have a solution but wanted to know if anyone had a easier solution for this.(like a one or 2 liner) Thanks in advance.

Replies are listed 'Best First'.
Re: Hash of Array Sort question
by ikegami (Patriarch) on Mar 18, 2010 at 15:27 UTC
    use strict; use warnings; use Data::Dumper qw( Dumper ); my $hash = { k1 => [5, 'b1', 'c1', 1], k2 => [4, 'b2', 'c2', 1], k3 => [4, 'b3', 'c3', 3], k4 => [5, 'b4', 'c4', 3], }; my $d_group; my $a_group; my $prio; for my $rec ( sort { $a->[3] <=> $b->[3] || $b->[0] <=> $a->[0] } values(%$hash) ) { if (!defined($d_group) || $rec->[3] != $d_group) { $d_group = $rec->[3]; $a_group = $rec->[0]; $prio = 1; } elsif ($rec->[0] != $a_group) { ++$prio; } $rec->[4] = $prio; } local $Data::Dumper::Sortkeys = 1; print(Dumper($hash));
    $VAR1 = { 'k1' => [ 5, 'b1', 'c1', 1, 1 ], 'k2' => [ 4, 'b2', 'c2', 1, 2 ], 'k3' => [ 4, 'b3', 'c3', 3, 2 ], 'k4' => [ 5, 'b4', 'c4', 3, 1 ] };

    Update: Added test code. Tested. Fixed bug in sort expression.

      There is one problem with that...the priority does not start from 1 for a different d_group
        It does in your example, and that's the only place you mentioned what the values for priority should be. If it's not right, you'll need to explain what it should be.
Re: Hash of Array Sort question
by Anonymous Monk on Mar 18, 2010 at 14:24 UTC
    I have a solution but wanted to know if anyone had a easier solution for this.(like a one or 2 liner) Thanks in advance.

    Show your solution

      Here is what i am doing I am sorting and using the index instead of actually writing it as a value in array

      my $hash; foreach my $csn (keys %$datastore) { push @{$hash->{$datastore->{$csn}->[3]}}, $datastore->{$csn}->[0]; } foreach (keys %$hash) { my @sorted = sort { $a <=> $b } @{$hash->{$_}}; $hash->{$_} = \@sorted; } foreach (keys %$datastore) { $datastore->{$_} = [$datastore->{$_}->[1],$datastore->{$_}->[2],$d +atastore->{$_}->[3], indexof($hash->{$datastore->{$_}->[3]}, $datasto +re->{$_}->[0])]; } sub indexof{ my ($array_ref, $search_for) = (shift, shift); my @array = @$array_ref; my( $index )= grep { $array[$_] eq $search_for } 0..$#array; return ($index + 1); }

      Created an other hash with each unique d as key and value is a array ref with sorted a's and then use the index

        Sorting the elements of the array wasn't in your spec. Are you suppose to be doing that?