Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Logic for sorting of this given array

by ravish (Acolyte)
on Aug 28, 2003 at 05:21 UTC ( [id://287249]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,

I need help in sorting of array. My array is like this.

@array = ( { level => 1, department = 'Office of President', }, { level => 2, department = 'Recruiting', }, { level => 2, department = 'Software', }, { level => 3, department = 'MIS', }, { level => 3, department = 'System Operations', }, { level => 2, department = 'Pipe line', }, );
basically this is made for tree like structure, when i print this array , it prints like this :
Office of the President Recruiting Software MIS System Operations PipeLine
Currently the department is not sorted alphabetically beacuse my array is created on the basis of level and it is in sequence. Now i want to sort the department alphabetically. How will i do this. I want this array print like this :
Office of the President (Make this as base level) PipeLine Recruiting Software MIS System Operations etc.....
Thanks

update (broquaint): added <code> tags

Replies are listed 'Best First'.
Re: Logic for sorting of this given array
by Zaxo (Archbishop) on Aug 28, 2003 at 05:35 UTC

    The logic for multiple sorting is as follows,

    my @sorted = sort { $a->{'level'} <=> $b->{'level'} || $a->{'department'} cmp $b->{'department'} } @array;
    That works by the lazy evaluation of logical operators. If comparison by level is not a tie, the department comparison is not made.

    After Compline,
    Zaxo

Re: Logic for sorting of this given array
by gmax (Abbot) on Aug 28, 2003 at 10:58 UTC

    If you want a tree, why don't you use a real tree structure?

    Tree::DAG_Node is meant for cases like this one.

    #!/usr/bin/perl -w use strict; use Tree::DAG_Node; my $org = Tree::DAG_Node->new; # the root $org->name('Office of President'); # name it $org->new_daughter->name('Recruiting'); # first dept my $sw = Tree::DAG_Node->new; # new dept $org->add_daughter($sw); # add to root $sw->name('Software'); # name it $sw->new_daughter->name('MIS'); # add sub-depts $sw->new_daughter->name('System Operations'); $org->new_daughter->name('Pipe line'); # one more dept print map "$_\n", @{$org->draw_ascii_tree},"\n"; print $org->dump_names; __END__ output: | <Office of President> /-------------------+------------------\ | | | <Recruiting> <Software> <Pipe line> /------------\ | | <MIS> <System Operations> 'Office of President' 'Recruiting' 'Software' 'MIS' 'System Operations' 'Pipe line'

    You can also build a tree on the fly, from an existing list of lists. Notice that in this case the root is at the bottom (as in botanical trees ;-) )

    my $tree = [ [ 'Recruiting' ], [ [ 'MIS' ], [ 'System Operations' ], 'Software' ], [ 'Pipe line' ], 'Office of President' ]; my $org = Tree::DAG_Node->lol_to_tree($tree);

    For more examples, see Introduction to Tree::DAG_Node in Tutorials.

    Update Added code comments.

     _  _ _  _  
    (_|| | |(_|><
     _|   
    
Re: Logic for sorting of this given array
by broquaint (Abbot) on Aug 28, 2003 at 10:05 UTC
    Or you could have an actual nested tree e.g
    my %tree = ( "Office of President" => { Recruiting => undef, 'Pipe line' => undef, Software => { MIS => undef, 'System Operations' => undef, }, } ); print dump_tree(\%tree); sub dump_tree { my($tree, $indent) = ( $_[0], $_[1] || 0 ); my $ret = ''; for(sort keys %$tree) { $ret .= " " x $indent."$_\n"; $ret .= dump_tree($tree->{$_}, $indent + 2) if ref $tree->{$_} and ref $tree->{$_} eq 'HASH'; } return $ret; } __output__ Office of President Pipe line Recruiting Software MIS System Operations
    Which, as you can see, lends itself to a nice recursive subroutine to dump the given tree.
    HTH

    _________
    broquaint

    update: changed code to better reflect the desired data structure

Re: Logic for sorting of this given array
by CombatSquirrel (Hermit) on Aug 28, 2003 at 10:36 UTC
    I suppose Zaxo's code won't work for you, because you used the array to describe a nested structure with sub-departments and such. In general, if you describe nested structures, use nested structures.
    Have a look at the following code; I think it should solve your problem:
    #!perl use strict; use warnings; sub returnParsed { my ($array, $index, $level) = @_; my $levelhash = {}; while ($index < @$array) { last if ($array->[$index]->{'level'} < $level); if ($array->[$index]->{'level'} == $level) { $levelhash->{$array->[$index]->{'department'}} = returnParsed($array, $index + 1, $level + 1); } ++$index; } return $levelhash; } sub dumpSorted { my ($structure, $indent, $startindent) = @_; my $dumped = ''; for (sort keys %$structure) { $dumped .= " " x $startindent . "$_\n"; $dumped .= dumpSorted($structure->{$_}, $indent, $startindent + +$indent); } return $dumped; } my @array = ({ level => 1, department => 'Office of President', }, { level => 2, department => 'Recruiting', }, { level => 2, department => 'Software', }, { level => 3, department => 'MIS', }, { level => 3, department => 'System Operations', }, { level => 2, department => 'Pipe line', }, ); print dumpSorted(returnParsed(\@array, 0, 1), 3, 3);
    Hope this helped.
    CombatSquirrel.
    Entropy is the tendency of everything going to hell.
      THanks for the help, it is usefull. But i have another problem that i need to pass more parameters in my array along with the level and department. it could be more than 3-4 now my array is like this : my @array = ({ level => 1,department => 'Office of President', linkdetails = "something"},
      { level => 2, department => 'Recruiting',linkdetails = "something1" },
      { level => 2, department => 'Software',linkdetails="something2"},
      etc.....
      how will i pass all these information along with the department ?. Actually i want to make on resultant array of
      hashes that will contain all the values so that i can
      pass to HTML template abd can print there. So level is
      also needed so that while printing in HTML page i can multiply the level into number of spaces.
      my resultant array of hashes after sorting look like this :

      my @array = ({ level => 1, department => 'Office of President',},
      { level => 2, department => 'Pipe line',link="",},
      { level => 2, department => 'Recruiting',link=""},
      { level => 2, department => 'software',link="" },
      { level => 3, department => 'MIS',link="" },
      { level => 3, department => 'System Operations',link="" },
      );

      need ur help in this ... Thanks
        Some pieces of advice:
        • Enclose array definitions, etc. in <code>-blocks
        • It's not link="", but link => "", or you'll get a syntax error
        • Capitalisation increases legibility ;-)
        To the code:
        #!perl use strict; use warnings; use Data::Dumper; sub returnParsedRec { my ($array, $index, $level) = @_; my $levelhash = {}; my $otherfields; while ($index < @$array) { last if ($array->[$index]->{'level'} < $level); if ($array->[$index]->{'level'} == $level) { $otherfields = {}; for (keys %{$array->[$index]}) { $otherfields->{$_} = $array->[$index]->{$_} unless ($_ eq 'level' or $_ eq 'department'); } $levelhash->{$array->[$index]->{'department'}} = [ $otherfields, returnParsedRec($array, $index + 1, $lev +el + 1) ]; } ++$index; } return $levelhash; } sub unParseRec { my ($levelhash, $result, $level) = @_; my $tmphash; for (sort keys %$levelhash) { $tmphash = $levelhash->{$_}->[0]; $tmphash->{'department'} = $_; $tmphash->{'level'} = $level; push @$result, $tmphash; unParseRec($levelhash->{$_}->[1], $result, $level + 1); } return $result; } sub returnParsed { return returnParsedRec(shift, 0, 1); } sub unParse { unParseRec(shift, [], 1); } my @array = ( { level => 1,department => 'Office of President', linkdetails => "some +thing"}, { level => 2, department => 'Recruiting',linkdetails => "something1" } +, { level => 2, department => 'Software', linkdetails => "something2"},) +; my $struct = returnParsed(\@array); print Dumper($struct); #print Dumper \@array; print "\n" . "=" x 70 . "\n\n"; print Dumper(unParse($struct));
        Be aware that HTML should not be formatted with spaces, look for lists (<ul>, <ol>, <dl>) and tables.
        Hope this helped.
        CombatSquirrel.
        Entropy is the tendency of everything going to hell.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2024-04-19 06:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found