title: How can I sort an array or table by column in Perl?
body: <p>I've been looking everywhere for an answer to this, and I just can't get it to work.</p>
  <p>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:</p>
  <pre class="lang-none prettyprint-override"><code>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
  </code></pre>
  <p>I need to sort this table by the last column in descending order. So my output should be:</p>
  <pre class="lang-none prettyprint-override"><code>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
  </code></pre>
  <p>I've tried a few approaches, but none have worked. Here's the code I've tried:</p>
  <pre><code>@input = &lt;FILENAME&gt;;
  
  #Close the file
  close FILENAME;
  
  my @fractions;
  my $y = 0;
  for (my $x = 1; $x &lt;= $#input; ++$x) {
      $fractions[$y] = (split (/\s/, $input[$x]))[4];
      ++$y;
  }
  my @sorted = sort {$b &lt;=&gt; $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 &gt; $#input);
  
      do {
          ++$z;
      } until ($sorted[$z] != $sorted[$z - 1]);
  
      $e = 0;
  } until ($z &gt; $#sorted);
  
  for (my $h = 0; $h &lt;= $#final; ++$h) {
      print $final[$h] . &quot;\n\n&quot;;
  }
  </code></pre>
  <p>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.</p>
  <p>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.</p>
  <p>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.</p>
  <pre><code>@input = &lt;FILENAME&gt;;
  close FILENAME;
  my @sorted = sort { $b-&gt;[4] &lt;=&gt; $a-&gt;[4] } @input;
  for (my $h = 0; $h &lt;= $#sorted; ++$h) {
      print $sorted[$h] . &quot;\n\n&quot;;
  }
  exit;
  </code></pre>
  <p>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.</p>
  <p>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.</p>
  <p>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.</p>
  <p>What am I doing wrong with the sort command? Is there a better way to do this?</p>