Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort an array or table by column in Perl?

Tags:

sorting

perl

I've been looking everywhere for an answer to this, and I just can't get it to work.

I have an input file that is read into an array using Perl. The file is a text file containing a table. Perl reads it in as an array, with each element being a full line (including all five columns). This is what the array looks like:

0__len__340      16    324       0    0.0470588235294118
1__len__251      2     249       0    0.00796812749003984
2__len__497      0     497       0    0
3__len__55       7     48        0    0.127272727272727
4__len__171      0     171       0    0
5__len__75       0     75        0    0
6__len__160      75    85        0    0.46875
7__len__285      1     284       0    0.00350877192982456
8__len__94       44    50        0    0.468085106382979

I need to sort this table by the last column in descending order. So my output should be:

6__len__160     75    85       0    0.46875
8__len__94      44    50       0    0.468085106382979
3__len__55      7     48       0    0.127272727272727
0__len__340     16    324      0    0.0470588235294118
1__len__251     2     249      0    0.00796812749003984
7__len__285     1     284      0    0.00350877192982456
2__len__497     0     497      0    0
4__len__171     0     171      0    0
5__len__75      0     75       0    0

I've tried a few approaches, but none have worked. Here's the code I've tried:

@input = <FILENAME>;

#Close the file
close FILENAME;

my @fractions;
my $y = 0;
for (my $x = 1; $x <= $#input; ++$x) {
    $fractions[$y] = (split (/\s/, $input[$x]))[4];
    ++$y;
}
my @sorted = sort {$b <=> $a} @fractions;
my $e = 1;
my $z = 0;
my $f = 0;
my @final;

do {
    do {
        if ((split (/\s/, $input[$e]))[4] == $sorted[$z]){
            $final[$f] = $input[$e];
            ++$e;
            ++$f;
        } else {
            ++$e;
        }
    } until ($e > $#input);

    do {
        ++$z;
    } until ($sorted[$z] != $sorted[$z - 1]);

    $e = 0;
} until ($z > $#sorted);

for (my $h = 0; $h <= $#final; ++$h) {
    print $final[$h] . "\n\n";
}

With this one, I basically tried to put the column 5 numbers into their own array, sort them, and then go back through the original array and pull out the elements that match the sorted array, and put them into the final array.

This may work if I keep working on it, but it takes so long to run that it's impractical. This small table I'm using to test my code with took a long time for this to run, and once the code is working it will be dealing with a table that has millions of rows.

I also tried applying the sort command to the table itself, but my output is the exact same table as my input...it doesn't get sorted.

@input = <FILENAME>;
close FILENAME;
my @sorted = sort { $b->[4] <=> $a->[4] } @input;
for (my $h = 0; $h <= $#sorted; ++$h) {
    print $sorted[$h] . "\n\n";
}
exit;

Lastly, I tried to put the array into a hash where the key was the first four columns, since the first column name is unique, and the values being the fifth column.

Then I hoped I could sort the hash by the values and the keys would stay with their assigned values. I couldn't get this to work either, though unfortunately it was a couple days ago and I erased the code.

One problem was that I couldn't figure out how to split the string only before the fifth column, so I end up with two strings, one containing the first four columns and one containing the fifth.

What am I doing wrong with the sort command? Is there a better way to do this?

like image 335
Lisa Avatar asked Nov 24 '14 19:11

Lisa


People also ask

How do I sort an array in Perl?

Perl has a built-in sort() function to sort an array of alphabets and numbers. When an array is passed to the sort() function it returns a sorted array. Sorting of Arrays in Perl can be done in multiple ways: Use of ASCII values to sort an Array.

How do you sort data in an array?

The sort() sorts the elements of an array. The sort() overwrites the original array. The sort() sorts the elements as strings in alphabetical and ascending order.

Which operator is used to arrange array items in character Order Perl?

Perl has two operators that behave this way: <=> for sorting numbers in ascending numeric order, and cmp for sorting strings in ascending alphabetic order. By default, sort uses cmp -style comparisons.

Can we sort elements in array?

The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted.


1 Answers

In your last code example you can replace

my @sorted = sort { $b->[4] <=> $a->[4] } @input;

with

my @sorted = sort { (split(' ', $b))[4] <=> (split(' ', $a))[4] } @input;

or even

my @sorted = sort { (split(/\s+/, $b))[4] <=> (split(/\s+/, $a))[4] } @input;

if input data has no lines with leading spaces.

like image 79
mpapec Avatar answered Nov 02 '22 17:11

mpapec