?
Solved

Perl sort question inside of a for loop

Posted on 2016-11-21
10
Medium Priority
?
85 Views
Last Modified: 2017-01-31
I'm trying to sort a list of data that I'm reading from a file and putting inside of an array. I want to sort the data by date and status.  I'm having trouble sorting because I think there's nothing to compare so it just spits it out as it's read.  I don't know if I need to pass the data somewhere first before I'm able to sort it or finish the loop then sort it. In any case, please help and let me know if you need more clarification.

Thanks!

.....

for my $i ("01" .. "30") {
        `download files`;
        open(my $fh, '< ', $download_path.'/'.$file.'-'.$i) or die("Could not open file $file-$i: $!.");

        while (my @row = <$fh>) {
                chomp @row;
                @arr = split ' ', $row[0];
        }

        my ($date, $path, $level, $num, $status) = @arr[2,4,7,8,9];
        my @pop_path = split '/', $first[4];
        my $title = $pop_path[3];
        my $day = UnixDate($date, "%Y-%m-%d %H:%M:%S");

        @sorted = (
        {
                date => $day,
                title => $title,
                path => $path,
                level => $level,
                num => $num,
                status => $status,
        }
        );

        @sorted = sort {
                $b->{date} cmp $a->{date}
        } @sorted;

        foreach my $line (@sorted){
                printf "%-22s %-15s %-4s %-2s %-5s %-30s\n" => @{$line}{qw(date title level num status path)};
        }

        close($fh);
}

.....
0
Comment
Question by:akatsuki27
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
  • 2
10 Comments
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41896789
As you are just using standard date stamps, you could use a simple utility such as 'sort' on linux or cygwin to do a multi column sort. Or import your file to something like Excel and do a multi column sort there.
0
 
LVL 28

Expert Comment

by:FishMonger
ID: 41896792
Your code has a number of problems, but instead of rewriting your code I'll point you to a youtube video of a YAPC talk about the use of map, grep and sort.  The sort portion of the talk gives at least one example of sorting by date fields.
0
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41896856
Can you supply a sample of your input file? I think this could be solved with a sort one-liner if that's any help.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:akatsuki27
ID: 41896951
Here's a sample of what's being read from the input:

20161113               title1       lev  1  comp  /some/path    
20161114               title2       lev  1  comp  /some/path  
20161115               title1       lev  2  comp  /some/path    
20161116               title1       lev  3  fail      /some/path

I want to be able to sort by date and then by status (5th column) if the date is the same. Does the sort need to be outside the loop or what?  I'm not an experienced coder, I just do small scripts like these for certain tasks so I'm sure there are probably cleaner ways to do this.
0
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41896998
If you are on Unix type system, you could just do this
sort -k1 -k5 input.txt > sorted.txt
Assuming you have spaces between columns. Use the -t option to specify another field delimiter.
0
 

Author Comment

by:akatsuki27
ID: 41897615
If it's okay, can you suggest a solution using Perl? The sorting of the data is just one step to continue manipulating the data for another purpose. I just got stuck in that part of the script so I came here for some direction using Perl only, please.  Also, I'd rather not have to make too many system calls because I'm testing with a small amount of data.  Once the script is live, the amount of data processed will be huge and the script will be too taxing.  Btw, yes this will run on a *nix system.
0
 
LVL 28

Assisted Solution

by:FishMonger
FishMonger earned 2000 total points
ID: 41898015
Did your watch the youtube video I pointed you to?

Instead of manually writing the sorting code our selves as shown in the video, we could use one of the soting modules on cpan.
Sort::Fields
#!/usr/bin/perl

use warnings;
use strict;
use Sort::Fields;
use Data::Dumper;

chomp(my @unsorted = <DATA>);
my @sorted = fieldsort ['1n', 4], @unsorted;

print Dumper \@sorted;

__DATA__
20161114               title2       lev  1  comp  /some/path
20161113               title1       lev  1  comp  /some/path
20161116               title1       lev  3  fail  /some/path
20161115               title1       lev  2  comp  /some/path

Open in new window


c:\test>test.pl

$VAR1 = [
          '20161113               title1       lev  1  comp  /some/path',
          '20161114               title2       lev  1  comp  /some/path',
          '20161115               title1       lev  2  comp  /some/path',
          '20161116               title1       lev  3  fail  /some/path'
        ];

EDIT:
I didn't realize how old that module was (1998) until after I posted, so it's not the best choice, but it does work.  There are more up-to-date modules available, or you can write the sort code yourself, which is pretty easy.
0
 

Accepted Solution

by:
akatsuki27 earned 0 total points
ID: 41898058
Thanks, FishMonger.  Honestly, I only saw part of the video since it was late at night and it's close to an hour.  I will check it out completely later though because I'm interested in learning more Perl.

But I was able to figure it out by writing it out myself. I pushed the incoming data into an array and sorted the array outside of the for loop. I put the print statement outside the loop also. Not pretty but it's working. The change in bold below:

....
        my @temp = (
        {
                date => $day,
                title => $title,
                path => $path,
                level => $level,
                num => $num,
                status => $status,
        }
        );

       foreach my $line (@temp){
                push (@sorted, $line);
        }


        close($fh);
}

@sorted = sort {  
        $a->{lnum} cmp $b->{num} ||
        $b->{date} <=> $a->{date}
} @sorted;

foreach my $sort (@sorted){
        printf "%-22s %-15s %-4s %-2s %-5s %-30s\n" => @{$sort}{qw(date title level num status path)};
}

.....
0
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41898500
Glad you worked out a Perl solution. You can also use awk, it's well suited to this type of problem?
0
 

Author Closing Comment

by:akatsuki27
ID: 41902982
I wasn't given a satisfactory answer before I figured it out on my own.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question