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

I am trying to sort a list with values that look like:
000_FFF0_0000 0011_FFF0_0010 00111_FFF00_00011
0 being an integer and F being an alpha character. My code currently looks like:
foreach my $peptide_id (sort { ($a =~ /(\d*)_FFF(\d*)_(\d*)/)[0] <=> ($b =~ /(\d*)_FFF(\d*)_(\d*)/)[0]}
This works, but is only sorting on $1 (first \d*). I am unsure how to sort on all 3 regex extractions. Ideally, it would combine the 3 ($1$2$3) and just sort on that value. But can't figure out how to do this. Any help would be greatly appreciated!

Replies are listed 'Best First'.
Re: Sorting on multiple variables
by ikegami (Patriarch) on Jul 22, 2009 at 23:45 UTC
    sort { my ($a1,$a2,$a3) = $a =~ /(\d*)_FFF(\d*)_(\d*)/; my ($b1,$b2,$b3) = $b =~ /(\d*)_FFF(\d*)_(\d*)/; $a1 <=> $b1 || $a2 <=> $b2 || $a3 <=> $b3 }

    Update: If you want to avoid the redundancy:

    map $_->[0], sort { $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] || $a->[3] <=> $b->[3] } map [ $_, /(\d*)_FFF(\d*)_(\d*)/ ],
      Proof that if your sorting key is complex enough, the Schwartzian Transform simplifies a sort rather than being merely an optimization; it saves you from repeating yourself or introducing temporaries into a sort block. :)
      Amazing! That worked like a charm. Thanks very much!!
Re: Sorting on multiple variables
by Bloodnok (Vicar) on Jul 23, 2009 at 00:03 UTC
    How about:
    use warnings; use strict; print sort { my @a = ($a =~ /(\d*)_FFF(\d*)_(\d*)/); my @b = ($b =~ /(\d*)_FFF(\d*)_(\d*)/); my $i=0; for ($i=0; $i < $#a && $a[$i] == $b[$i]; $i++){} $a[$i] <=> $b[$i]; } <DATA>; __DATA__ 0011_FFF0_0010 00111_FFF00_00011 000_FFF0_0000
    Gives:
    $ perl /tmp/tst.pl 000_FFF0_0000 0011_FFF0_0010 00111_FFF00_00011
    Not exactly exhaustive, but I submit it makes a not unreasonable basis for experimentation...

    Update:

    ...which is a variant on the solution with which ikegami beat me to the draw:-)

    A user level that continues to overstate my experience :-))
Re: Sorting on multiple variables
by salva (Canon) on Jul 23, 2009 at 06:35 UTC
    You can use Sort::Key::Multi:
    use Sort::Key::Multi qw(i3_keysort); # i3 => 3 integer keys my @sorted = i3_keysort { /(\d*)_FFF(\d*)_(\d*)/ } @data;
      Thank you for the solution. This also works. Elegant approach.
Re: Sorting on multiple variables
by susanti13 (Novice) on Jul 22, 2009 at 23:53 UTC
    I'm trying to understand the sorting that you want.
    Based on the 3 values that you gave, what result do you want to achieve?