简体   繁体   中英

How to sort perl hash?

I have the below hash structure, hash of hash.

$VAR1 = { '191' => { 'test1' => { 'score' => '9.18' }, 'test2' => { 'score' => '2.84' }, 
                     'test3' => { 'score' => '15.62' }, 'test4' => { 'score' => '11.84' }, 

          '190' => { 'test1'=> { 'score' => '13.28' }, 'test2' => { 'score' => '-47.56' }, 
                     'test3' => { 'score' => '18.50' }, 'test4' => { 'score' => '14.88' } } }

I am trying to sort the hash based on the 'score' value. The sorting should happen only among whats inside of the main keys '191' and '190'. See below hash structure for expected result.

$VAR1 = { '191' => {'test3' => { 'score' => '15.62' }, 'test4' => { 'score' => '11.84' }
                    'test1' => { 'score' => '9.18' }, 'test2' => { 'score' => '2.84' }, 
                     
        ​ '190' => { 'test3' => { 'score' => '18.50' }, 'test4' => { 'score' => '14.88' }
                    'test1'=> {'score' => '13.28' }, 'test2' => { 'score' => '-47.56' } } }

Sorting is to be done based on descending score value.

I have tried out the below code but it kind-of sorts based on the main-key. I need output as shown in the expected hash structure.

my @sort_by_rank;
for my $key1 (keys %rankBased) {
    for my $key2 (keys %{$rankBased{$key1}}) {
        @sort_by_rank = sort{ $rankBased{$b}{$key2}{score} <=> $rankBased{$a}{$key2}{score}
                            } keys %rankBased;
    }   
}

Here %rankBased is the hash.

Please help.

You can't sort a hash, but you can sort the list of a hash's keys.

for my $student_id (keys %tests_by_student_id) {
   my $tests = $tests_by_student_id{$student_id};
   my @sorted_test_ids =
      sort { $tests->{$b}{score} <=> $tests->{$a}{score} }
         keys(%$tests);

   # Do something with the student's sorted tests here.
}

(Meaningless %rankBased renamed to %tests_by_student_id .)


The above is great is you want to do something with each student. But if you actually want to "sort the hash", you'll need to switch to a different structure.

for my $student_id (keys %tests_by_student_id) {
   # This next line is the same as 
   # my $tests = $tests_by_student_id{$student_id};
   # except changing $tests also changes
   # $tests_by_student_id{$student_id}.
   for my $tests ($tests_by_student_id{$student_id}) {
      $tests = [
         sort { $b->{score} <=> $a->{score} }
            map { { id => $_, %{ $tests->{$_} } } }
               keys(%$tests)
      ];
   }
}

This produces

$VAR1 = {
   '191' => [ { id => 'test3', score =>  15.62 },
              { id => 'test4', score =>  11.84 },
              { id => 'test1', score =>   9.18 },
              { id => 'test2', score =>   2.84 } ],
   '190' => [ { id => 'test3', score =>  18.50 },
              { id => 'test4', score =>  14.88 },
              { id => 'test1', score =>  13.28 },
              { id => 'test2', score => -47.56 } ],
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM