Bigby
Bigby

Reputation: 303

Sorting an Input List

I have an input list that is being provided by a system that tracks metrics. I need to sort it in order to remove usage data that is below a given threshold and I really have no idea how to approach it. The data that is fed to me should look similar to this:

ID                    Usage                  Estimated Cost
------------------------------------------------------------------
University Name       260000                 1600.00

The first field will be a name, and the following two fields will be integer values. I was thinking about trying to create list of lists, but there is probably an easier way. How would I go about removing just getting the 3 fields and sorting them by the usage value?

Upvotes: 0

Views: 109

Answers (3)

ErikR
ErikR

Reputation: 52039

The standard approach is to create a list of hashes. In your case you would convert your input file into something:

my @records = (
  { ID => "University Name", Usage => 260000, EstCost => 1600.00 },
  { ID => "...", Usage => 12345, EstCost => 9999.99 },
  ...

);

Then sort them (e.g. by Usage) with code like:

my @sorted = sort { $a->{Usage} <=> $b->{Usage} } @records;

Then create a report from the sorted records with code like:

for my $r (@sorted) {
  print "ID: ", $r->{ID}, ..., "\n";
}

You can take short cuts if you want, but transforming each line into a hash has several advantages:

  • it makes your code easier to read, understand and modify - i.e. it is obvious that sort { $a->{Usage} <=> $b->{Usage} ... sorts by Usage
  • there are so many other libraries which operate on list of hashes, i.e. there are libraries which convert list of hashes to a CSV file or an HTML table or a plain text table or insert the rows into a database, etc.

Upvotes: 1

choroba
choroba

Reputation: 241948

You can remember the whole line so you do not have to format it again. Also, only remember and sort the lines whose usage value is over the threshold:

perl -ane 'BEGIN { $threshold = 2000 }              # Insert your value here.
           next if 1 .. 2 or $F[-2] < $threshold;   # Skip the header and filtered lines.
           push @A, [ $F[-2], $_ ];                 # Remember the usage and the whole line.
           }{                                       # At the end...
           print map $_->[1],
                 sort { $a->[0] <=> $b->[0] } @A'

Upvotes: 2

evil otto
evil otto

Reputation: 10582

A list of lists is pretty easy.

my @list;
while(<>) {
    push @list, [$_,(split(/\s+/,$_,3))[1]];
}
foreach my $out (sort {$a->[1] <=> $b->[1]} @list) {
    print $out->[0];
}

Upvotes: 2

Related Questions