Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

sorting in hashes

by Anonymous Monk
on Aug 22, 2009 at 13:18 UTC ( [id://790563]=perlquestion: print w/replies, xml ) Need Help??

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

my %hash=(inst => { dept1 => { rollno=> { [name,marks], [name1,marks1], }, inst2.... });
how can I sort marks in descending order across the departments and institutes?

Replies are listed 'Best First'.
Re: sorting in hashes
by james2vegas (Chaplain) on Aug 22, 2009 at 13:24 UTC
    please put your code between <code> </code> tags, like this
    my %hash=(inst => { dept1 => { rollno=> { [name,marks], [name1,marks1] +, }, inst2.... });


    do you want to sort by inst, dept, marks?
    I think we need a little more description of your structure, rollno is that a constant, or is it a value like isnt or dept1? why are the marks in array refs inside a hashref, which wouldn't work if you had an odd number of names. You would want them either in an arrayref like rollno => [ [name, marks], ... ] or in a hashref like rollno => { name => marks, name => marks, ... }.

    And as mentioned in another response, supply what your data would look like sorted.
        Also, please
      1. expand your sample data to include multiple institutes with multiple departments (instead of just ....), and
      2. provide an example of the output or data structure you are trying to achieve with the sort, that matches the expanded sample data.
Re: sorting in hashes
by tmharish (Friar) on Aug 22, 2009 at 14:03 UTC
    As zwon has pointed out your Structure is not too clear - If it is:
    %hash = ( inst => { dept1 => { rollno=> { name => marks, name1 => marks1 }, ... }, ... } ... inst2 ... );
    A - rather long, and inefficient solution - but one that is readable and hopefully instructive is below:
    use strict; use Data::Dump qw( dump ); my %hash = ( inst => { dept => { rollno=> { name => 100, name1 => 90 , name2 => 30 , name3 => 99 } } } ); my @all_insts = keys %hash; my @all_deps; foreach my $single_inst ( @all_insts ) { push @all_deps, keys %{ $hash{ $single_inst } }; } my @all_roll_nos; foreach my $single_inst ( @all_insts ) { foreach my $single_dep ( @all_deps ) { push @all_roll_nos, keys %{ $hash{ $single_inst }->{ $single_dep } + }; } } my @all_names; foreach my $single_inst ( @all_insts ) { foreach my $single_dep ( @all_deps ) { foreach my $single_roll_no ( @all_roll_nos ) { push @all_names, keys %{ $hash{ $single_inst }->{ $single_dep +}->{ $single_roll_no } }; } } } my @all_marks ; foreach my $single_inst ( @all_insts ) { foreach my $single_dep ( @all_deps ) { foreach my $single_roll_no ( @all_roll_nos ) { foreach my $single_name ( @all_names ) { push @all_marks, $hash{ $single_inst }->{ $single_dep }->{ $si +ngle_roll_no }->{ $single_name }; } } } } my @sorted_marks = sort( { $a <=> $b } @all_marks ); dump( @sorted_marks );
Re: sorting in hashes
by Util (Priest) on Aug 22, 2009 at 16:32 UTC
    Assuming that I have guessed correctly at the structure of your missing example data, this solves the problem.
    #!/usr/bin/perl use strict; use warnings; my %institute_department_roll_name_mark_HoHoHoH = ( CIA => { HUMINT => { rollno1 => { Bob => 65, Adam => 87, }, rollno2 => { Dennis => 37, Arthur => 41, }, }, SIGINT => { rollno1 => { Harry => 87, Albus => 100, }, rollno2 => { M => 70, Q => 98, James => 75, }, }, }, NSA => { Encryption => { rollno1 => { Abel => 13, Baker => 28, Charlie => 57, }, rollno2 => { Roger => 2, Fox => 3, Dog => 2, }, }, Decryption => { rollno1 => { Marin => 62, Chong => 66, }, rollno2 => { Dave => 0, }, }, }, ); # Create a flattened data structure. my $h1 = \%institute_department_roll_name_mark_HoHoHoH; my @institute_department_roll_name_mark_AoH; while ( my ( $institute, $h2 ) = each %{$h1} ) { while ( my ( $department, $h3 ) = each %{$h2} ) { while ( my ( $roll, $h4 ) = each %{$h3} ) { while ( my ( $name, $mark ) = each %{$h4} ) { push @institute_department_roll_name_mark_AoH, { INST => $institute, DEPT => $department, ROLL => $roll, NAME => $name, MARK => $mark, }; } } } } @institute_department_roll_name_mark_AoH = sort { $b->{MARK} <=> $a->{MARK} or $a->{INST} cmp $b->{INST} or $a->{DEPT} cmp $b->{DEPT} or $a->{ROLL} cmp $b->{ROLL} or $a->{NAME} cmp $b->{NAME} } @institute_department_roll_name_mark_AoH; for my $href (@institute_department_roll_name_mark_AoH) { printf "%7d\t%-7s\t%-15s\t%-7s\t%s\n", @{$href}{qw( MARK INST DEPT ROLL NAME )}; }
    Output:
    100 CIA SIGINT rollno1 Albus 98 CIA SIGINT rollno2 Q 87 CIA HUMINT rollno1 Adam 87 CIA SIGINT rollno1 Harry 75 CIA SIGINT rollno2 James 70 CIA SIGINT rollno2 M 66 NSA Decryption rollno1 Chong 65 CIA HUMINT rollno1 Bob 62 NSA Decryption rollno1 Marin 57 NSA Encryption rollno1 Charlie 41 CIA HUMINT rollno2 Arthur 37 CIA HUMINT rollno2 Dennis 28 NSA Encryption rollno1 Baker 13 NSA Encryption rollno1 Abel 3 NSA Encryption rollno2 Fox 2 NSA Encryption rollno2 Dog 2 NSA Encryption rollno2 Roger 0 NSA Decryption rollno2 Dave
Re: sorting in hashes
by targetsmart (Curate) on Aug 22, 2009 at 13:38 UTC
    sort


    Vivek
    -- 'I' am not the body, 'I' am the 'soul', which has no beginning or no end, no attachment or no aversion, nothing to attain or lose.
Re: sorting in hashes
by zwon (Abbot) on Aug 22, 2009 at 13:41 UTC

    It's not very clean from you description what structure do you have (there are more '{' than '}') and how exactly do you want to sort it, so can you provide us this more thorough description? Generally it looks like you need to sort array of hashes, perhaps several times. Have a look onto sort, there's example of sorting array of hashes.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://790563]
Approved by zwon
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2024-03-28 10:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found