http://www.perlmonks.org?node_id=489995

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

Hi,

I'm sure this question has been asked before, but I can't seem to find an answer using super search...

I have a file which is 22 columns delimited by a tab. I want to sort it first by column 9, then by column 22. I'm not sure how to proceed in modifying the Schwartzian transform to accomplish this. This is what I have, but it doesn't seem to be working:

@sortedarry = map { $_ ->[0] } sort { $a->2 <=> $b->2 } sort { $a->[1] cmp $b->[1] } map { my @cols = split /\t/; [$_, $cols[9], $cols[22] ]; } @foo; print "$_\n" foreach @sortedarry;

Replies are listed 'Best First'.
Re: schwartzian transform and sorting on two columns
by borisz (Canon) on Sep 07, 2005 at 20:54 UTC
    just sort in one go:
    @sortedarry = map { $_ ->[0] } sort { $a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] } map { my @cols = split /\t/; [$_, $cols[9], $cols[22] ]; } @foo;
    Boris
Re: schwartzian transform and sorting on two columns
by ikegami (Patriarch) on Sep 07, 2005 at 21:55 UTC

    Three problems:

    1) You're missing square brackets around your array indexes in the topmost sort.

    2) @cols is 0-based, so the 9th and 22nd column are in $cols[8] and $cols[21] respectively. You said there are only 22 colums, so $cols[22] is wrong.

    3) Your sorts are in the wrong order. The higher precedence one should be at the top to make it execute last.

    Finally, borisz is right. It'll be faster if you combine your two sorts into one.

    @sortedarry = map { $_ ->[0] } sort { $a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] } map { my @cols = split /\t/; [ $_, $cols[8], $cols[21] ] } @foo; print "$_\n" foreach @sortedarry;
Re: schwartzian transform and sorting on two columns
by BUU (Prior) on Sep 07, 2005 at 20:54 UTC
    It sounds like you want:
    sort { $a <=> $b or $c cmp $d }
      I know that $a and $b are perl's special variables that are used in sort, but these new $c & $d variables are a mystery...

      thor

      Feel the white light, the light within
      Be your own disciple, fan the sparks of will
      For all of us waiting, your kingdom will come

Re: schwartzian transform and sorting on two columns
by salva (Canon) on Sep 08, 2005 at 08:07 UTC
    forget about the Schwartzian transform and use Sort::Key:
    use Sort::Key::Maker sn_keysort => qw(str num); my @sortedarry = sn_keysort { (split /\t/)[8, 21] } @foo;