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

Hi monks, This is my first question since joining this site. Basically what I'm trying to do is grab the drivespace info in solaris, using df-k and try to compare this info to the same info, grabbed in another way. I am trying to sort this info that I just grabbed and then compare it later. I am having trouble with sorting it. I have a 2-dim array with scalars like:
4129290 1675967 2412031 41% /usr
The subroutine sorter is in a package and is called by the main program.
sub sorter (@) { @beforeSort=@_; print "before sort: $beforeSort[2][4]\n"; @sorted_by_drive=sort{$a->[4] cmp $b->[4]} @beforeSort; print "Sorted by drive: $sorted_by_drive[2][4]\n"; return @sorted_by_drive; }
the 'print "before sort: ' gives a value of 2356 (I verified and it is a correct value)

The 'print "Sorted by drive:...." line prints nothing. The returned values are memory references but I found that I cannot refer to the data explicitly after sorting. UPDATE

Thanks for your replies, however, I did not explicitly create the 2-dim array. I used references to create the array when I read df-k information from Solaris:
sub parseIntoArraySolaris (@df) { $arrayCount=0; @rows; @col0; @col1; @col2; @col3; @col4; @col5; @col6; @col7; @col8; @col9; @col10; $rows[0]=\@col0; $rows[1]=\@col1; $rows[2]=\@col2; $rows[3]=\@col3; $rows[4]=\@col4; $rows[5]=\@col5; $rows[6]=\@col6; $rows[7]=\@col7; $rows[8]=\@col8; $rows[9]=\@col9; $rows[10]=\@col10; foreach $element (@_) { ($a, $b, $c, $d, $e, $f)=split(/\s+/,$element); #split +s strings separated by spaces,tabs ###################################################################### +################## #$rows[0][x] is just the column headings, Filesystem, kbytes, used, av +ail etc. #$rows[not zero][x] are the actual data. #for Windows, telnet cannot get the disk info, so we have to save the +info into a file, #use the FTP package to ftp (using ftppackage.pl package) the file to +the local system, #and use this 2-dim array to parse the data from the file. ###################################################################### +################## $rows[$arrayCount][0]=$b/1024; $rows[$arrayCount][1]=$c/1024; $rows[$arrayCount][2]=$d/1024; $rows[$arrayCount][3]=$e/1024; $rows[$arrayCount][4]=$f/1024; #$rows[$arrayCount][5]=$f; print "$rows[$arrayCount][0]\n"; print "$rows[$arrayCount][1]\n"; print "$rows[$arrayCount][2]\n"; print "$rows[$arrayCount][3]\n"; print "$rows[$arrayCount][4]\n"; #print "$rows[$arrayCount][5]\n"; ########################## To get to the value of the array, use $arra +y[$row][$column]; ########################## example: print "This is: $rows[$arrayCount] +[5]\n"; $arrayCount++; } return @rows; #returns the entire two-dimensional array. }
I think it works if you explicitly put the values into a multi-dim array, but when it is passed by reference, it may have some problem. I'm getting nothing outputted by the 'print "Sorted by drive:...'.

Replies are listed 'Best First'.
Re: How do I sort a Multidimensional array (not Hash)?
by ikegami (Patriarch) on Sep 21, 2004 at 17:51 UTC

    It works for me. You didn't provide a test case, so I had to write my own:

    my @a = ( [4129290, 1675967, 2412031, '41%', '/usr/bin' ], [4129290, 1675967, 2412031, '41%', '/usr' ], [4129290, 1675967, 2412031, '41%', '/local' ], ); sorter(@a); __END__ output ====== before sort: /local Sorted by drive: /usr/bin

    btw, you should use my in front of @beforeSort and @sorted_by_drive, and you'd probably be better off (due to smaller memory utilisation) to accept an array reference as an argument instead of an array, and returning an array reference, instead of the array.

    Maybe you're not preparing the array properly? Here's an example:

    my @df_k = split(/\n/, `df -k`); shift(@df_k); # Remove header. my @sorted_by_drive = sort { $a->[5] cmp $b->[5] } map { [ split(/\s+/, $_, 6) ] } @df_k; use Data::Dumper (); print(Data::Dumper->Dump( [ \@sorted_by_drive ], [qw( $sorted_by_drive )], ));

    Updated reply to updated question:

    1) Please please please please use use strict! You're not good enough to not use it yet.

    2)

    sub parseIntoArraySolaris (@df) ^^ what does this mean? It compiles, surprisingly, but it's not listed in docs and it doesn't give the args to the var @df.

    3) Hold on, isn't [4] suppose to be a string? Why are you dividing a string by 1024? Similarly, [3] is a percentage, not an amount.

    4) The function could use "some" improvement:

    sub parseIntoArraySolaris { my @rows; my $element; foreach $element (@_) { my ($a, $b, $c, $d, $e, $f) = split(/\s+/, $element); push(@rows, [ $b/1024, $c/1024, $d/1024, $e, $f ]); } return @rows; }

    which can be rewritten as:

    sub parseIntoArraySolaris { return map { my ($a, $b, $c, $d, $e, $f) = split(/\s+/, $_); [ $b/1024, $c/1024, $d/1024, $e, $f ] } @_; }

    and here's how it's used:

    my @df_k = split(/\n/, `df -k`); shift(@df_k); # Remove header. my @beforeSort = parseIntoArraySolaris(@df_k); my @sorted_by_drive = sort { $a->[4] cmp $b->[4] } @beforeSort; use Data::Dumper (); print(Data::Dumper->Dump( [ \@sorted_by_drive ], [qw( $sorted_by_drive )], ));

    wich can be rewritten as:

    # Get data. my @df_k = split(/\n/, `df -k`); # Remove header. shift(@df_k); # Parse line. foreach (@df_k) { my ($a, $b, $c, $d, $e, $f) = split(/\s+/, $_); $_ = [ $b/1024, $c/1024, $d/1024, $e, $f ]; } # Sort. my @sorted_by_drive = sort { $a->[4] cmp $b->[4] } @df_k; # Quick way of printing for now. use Data::Dumper (); print(Data::Dumper->Dump( [ \@sorted_by_drive ], [qw( $sorted_by_drive )], ));
Re: How do I sort a Multidimensional array (not Hash)?
by tilly (Archbishop) on Sep 21, 2004 at 20:38 UTC
Re: How do I sort a Multidimensional array (not Hash)?
by bpphillips (Friar) on Sep 21, 2004 at 18:28 UTC
    I think there's some confusion with a few things (references, adding elements to arrays, etc). One thing that might be helpful is using Data::Dumper for debugging. Anyway, here's how I would do it:
    sub parseIntoArraySolaris { # this is what we'll return after we parse my @rows; foreach my $line(@_){ # here's a temporary array for each column's value # as we split it, we divide all the numbered # values by 1024 my @cols = map {m/^[\d.-]+$/ ? $_ / 1024 : $_} (split(/\s+/,$line))[0..5]; # just for debugging I'm assuming # see note below about using Data::Dumper print "$_\n" for(@cols); # add our parsed data for this line onto @rows # this is more idiomatic than how you were doing it # with the $arrayCount++ thing push(@rows,\@cols); } # now return all the data return @rows; } sub sorter { # this isn't very efficient for large arrays but # we're probably never doing very large data sets # for this problem my @rows = @_; # you might want to use Data::Dumper to do debugging # you just do a print "before sort: ".Dumper \@rows # and it'll give you a very nice dump of the data # structure print "before sort: $rows[2]->[4]\n"; my @sorted = sort{$a->[4] cmp $b->[4]} @rows; print "Sorted by drive: $sorted[2]->[4]\n"; return @sorted; }
Re: How do I sort a Multidimensional array (not Hash)?
by auyong (Novice) on Sep 21, 2004 at 19:37 UTC
    Thanks for all your help ikegami and bpphilips! At least now I have something that works and shorter code too!