in reply to sorting an array with mixed elements...

I presume you meant

print sort { (split ":", $a)[0] <=> (split ":", $b)[0] } @table;

sort {...} @table will sort the contents of the array @table according to the contents of {...}

sort works by comparing pairs of elements, calling them $a and $b within the {...}.

split ":", $a will split $a into a list using ":" as the separator

(...)[0] will return the first element of that list

So, given input like:

111:A:B;C 2:D:E:F

This will sort by looking at the first field only, namely "111" & "2", treating them as numbers because of the use of <=>.

update: Oops, I forgot to mention <=>, the numeric comparison operator, usually called the spaceship operator.

Replies are listed 'Best First'.
Re^2: sorting an array with mixed elements...
by cgmd (Beadle) on Jun 09, 2007 at 23:08 UTC
    I believe I'm confused by the occurrence and use of split(), sort() and print(), all, on one line. Is there a way to run these three functions separately, but sequentially?

    Thanks!

      print sort { (split ":", $a)[0] <=> (split ":", $b)[0] } @table;
      Is the same as:
      my @sorted = sort { my @A = split ':', $a; my @B = split ':', $b; $A[0] <=> $B[0]; } @table; print @sorted;

      You can't split it up completely, but you could write like so

      sub compare { (split ":", $a)[0] <=> (split ":", $b)[0] } my @sorted = sort compare @table; print @sorted;

      It would also benefit from applying a Schwartzian Transform (ST):

      print map { $_->[1] } sort { $a->[0] <=> $b->[0] } map { [ (split /:/, $_)[0], $_ ] } @table;

      A ST is read from the bottom up

      map { [ (split /:/, $_)[0], $_ ] } @table;

      creates an anonymous array with the thing you want to sort on as the first element ((split /:/, $_)[0]), and the original line as the second($_)

      sort { $a->[0] <=> $b->[0] }

      does the sort, using the first element of the arrays you just created

      map { $_->[1] }

      returns the original line from the second element of your arrays.

      There's loads of material on the interweb on the ST if you want to know more.

      update: fixed a couple of typos

        You can't split it up completely,

        Just a tiny bit more, mixing your "solution" with lidden's:

        sub compare { my @A = split /:/, $a; my @B = split /:/, $b; $A[0] <=> $B[0]; } my @sorted = sort compare @table; print @sorted;

        (Incidentally I also changed the first argument to split, since it must be a pattern - strings are automatically converted of course, but there's one special case, so...)

        If it ain't clear like this... I don't know what could ever be!!