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

This node falls below the community's threshold of quality. You may see it by logging in.

Replies are listed 'Best First'.
Re: How can I sort this data on the fourth field?
by Corion (Patriarch) on Aug 16, 2007 at 11:58 UTC
Re: How can I sort this data on the fourth field?
by FunkyMonk (Bishop) on Aug 16, 2007 at 12:05 UTC
    I'd use merlyn's Schwartzian Transform:
    chomp ( my @data = <DATA> ); my @sorted = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map [ $_, (split)[3] ], @data; print "$_\n" for @sorted; __DATA__ 0 TOTAL 11997 26981 0 root 1089 2594 1 daemon 0 0 594 pipmp01 591 1151 958 maestro 335 685

    Output:

    1 daemon 0 0 958 maestro 335 685 594 pipmp01 591 1151 0 root 1089 2594 0 TOTAL 11997 26981


      FunkyMonk,


      I am not sure where to insert this into my perl code. I am reading this data in from a file and I am
      skipping some lines of input. The beginning code is as follows:

      for my $file ("may_07_xsd00544.dat") { open (my $fh,"<",$file) or die "Can't open file $file: $!"; while (my $line = <$fh>) { chomp($line); last if ($line =~ /TOTAL COMMAND SUMMARY/); next if (($line =~ /^[a-zA-Z]/) or ($line =~ /^\s*$/) or ($line =~ /^ +\s/));
        You need to build an array (with push @data, $line;) inside your while loop, between that next and the closing brace.

        The sort snippet I posted should be placed after the closing brace of the while.

        Something like:

        my @data; while (my $line = <$fh>) { chomp($line); last if ($line =~ /TOTAL COMMAND SUMMARY/); next if (($line =~ /^[a-zA-Z]/) or ($line =~ /^\s*$/) or ($line =~ / +^\s/)); push @data, $line; } my @sorted = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map [ $_, (split)[3] ], @data;

        Going on the data you posted, wouldn't that next be better written as:

        next unless $line =~ /^\d/;

Re: How can I sort this data on the fourth field?
by dwm042 (Priest) on Aug 16, 2007 at 15:00 UTC
    If you can guarantee uniqueness of the field you're sorting on, and if you're going to be manipulating these data by the field itself, sometimes it's useful to use the sorted column as the keys of a hash and drop the rest of the data into the hash as an associative array:

    #!/usr/bin/perl use warnings; use strict; package main; my %data_set = (); while(<DATA>) { my @row = split/\s+/, $_; $data_set{$row[3]} = [ $row[0], $row[1], $row[2] ]; } foreach ( sort { $b <=> $a } keys %data_set ) { printf "%-6d -> %-4d %-7s %-6d\n", $_, $data_set{$_}->[0], $data_set{$_}->[1], $data_set{$_}->[2] +; } __DATA__ 0 TOTAL 11997 26981 0 root 1089 2594 1 daemon 0 0 594 pipmp01 591 1151 958 maestro 335 685
    The output is:

    C:\Code>perl hashsort.pl 26981 -> 0 TOTAL 11997 2594 -> 0 root 1089 1151 -> 594 pipmp01 591 685 -> 958 maestro 335 0 -> 1 daemon 0
Re: How can I sort this data on the fourth field?
by apl (Monsignor) on Aug 16, 2007 at 12:24 UTC
    What have you written so far?


      apl, I am reading this data from a large report and
      stripping out lines and then doing some calculations
      based on the input data and then producing an output
      file (but the output file is not sorted by the 4th
      field).


      My code is as follows:

      #!/usr/bin/perl use strict; use warnings; ########################################################## # # Parse PS Accounting Data # ########################################################## ## local @ARGV = qw/ may_07_xsd00544.dat /; my %usage; my $uid; my $login; my $cpupr; my $cpunpr; my $cpumin; my $cputot; my $cpupct; my $files = 0; ############################################### # ############################################### for my $file ("may_07_xsd00544.dat") { open (my $fh,"<",$file) or die "Can't open file $file: $!"; ############################################### # ############################################### for my $file ("may_07_xsd00544.dat") { open (my $fh,"<",$file) or die "Can't open file $file: $!"; open (my $OUTGOOD2,">","psapct2.csv") or die "Can't open OUT file: +$!"; print $OUTGOOD2 "Total =,"; while (my $line = <$fh>) { chomp($line); last if ($line =~ /TOTAL COMMAND SUMMARY/); next if (($line =~ /^[a-zA-Z]/) or ($line =~ /^\s*$/) or ($line =~ /^ +\s/)); my ($uid, $login, $cpupr, $cpunpr, @data) = (split("\t",$line)); $cpumin = $cpupr + $cpunpr; if ($login =~ /^TOTAL/) { $cputot = $cpumin; $cpupct = ($cpumin / $cputot)*100; printf $OUTGOOD2 ("%3.1f%%",$cpupct); print $OUTGOOD2 "\n"; } else { $cpupct = ($cpumin / $cputot)*100; printf $OUTGOOD2 ("$uid,$login,%3.1f%%,$cpumin \n" ,$cpupct); } } continue { $files++ if eof; } close $fh or die "Can't close result file: $!"; close $OUTGOOD2 or die "Can't close psapct2.csv data file: $!"; }