×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Jobs

Sorting

How do I sort columns/fields of mixed data? by KevinADC
Posted: 6 Feb 07 (Edited 15 Feb 07)

----------------------------
ignore this section:
code

----------------------------

Problem:

You have some data in a file (or array or hash or list) that needs sorting by several different fields and the fields are different types of data. Using a simple alpha (cmp) or  numeric (<=>) sort will not work. Some fields are alpha and some numeric (they could even be (aplha-numeric) and I need to sort the data using all the fields (or maybe just one or more fields) to get the correct order.

Solution:

Use map-sort-map, known commonly as a Schwartzian Transform.

CODE

  1. my @sorted = map {$_->[0]}
  2.              sort { $a->[1] cmp $b->[1] ||
  3.                     $a->[2] <=> $b->[2] ||
  4.                     $a->[3] <=> $b->[3] }
  5.              map {chomp;[$_,split(/,/)]} <DATA>;
  6. print "$_\n" for @sorted;
  7. __DATA__
  8. John,34,100.00
  9. John,33,100.00
  10. Jane,33,99.99
  11. Fred,22,44.2
  12. Johnny,33,99
  13. Andrew,19,38.29
  14. Chris,28,200
  15. William,60,2000
  16. Tom,42,1000
  17. Andy,20,38.29

Discussion:

Line 5 of the code snippet is where the sorting begins:

CODE

5.             map {chomp;[$_,split(/,/)]} <DATA>;

The map{} block reads in the lines from <DATA> (<DATA> could be an array or hash or any list you want to sort). First the record seperator is removed using chomp; then each line is stored as an annonymous array [$_,split(/,/)] consisting of four elements. Using the first line of the data as an example the annonymous array would look like this:

CODE

['John,34,100.00','John',34,100.00]

The first element is just a copy of the line left intact, which will be used later to store in the sorted array of data. Fields, or indices now, 1, 2, 3, will be used to properly sort each column of the data in the sort{} block. Thats what lines 2, 3, and 4 are doing:

CODE

2.             sort { $a->[1] cmp $b->[1] ||
3.                    $a->[2] <=> $b->[2] ||
4.                    $a->[3] <=> $b->[3] }

Because the data being sorted is in annonymous arrays we have to use the arrow notation '->' to access each element of the array and it's index number: [1], instead of just $a and $b like you normally see. The first sort is alpha (the names) and the others are numeric. Using the short circuit ||  operator allows the sort to cycle through each field if necessary to compute the final sort. It essentially reads:

if [1] are equal, compare [2], if [2] are equal, compare [3]

After all the sorting is done, line 1 (one)of the snippet:

CODE

1. my @sorted = map{$_->[0]}

uses the other map{} block to return the first element of each annonymous array of the sorted data to the final array @sorted. Remember, the first element of each annonymous array was a copy of each line of the unsorted data. You could return any one field of the data, or as many as you want, to the @sorted array in the map{} block. The sorted data is:

CODE

Andrew,19,38.29
Andy,20,38.29
Chris,28,200
Fred,22,44.2
Jane,33,99.99
John,33,100.00
John,34,100.00
Johnny,33,99
Tom,42,1000
William,60,2000

If you are confused by some of the code and explanations, don't worry. It took me a while to fully grasp all that this short bit of code is doing. Play around with it to get the feel of sorting complex data.

Use the link below to contact me about corrections or additions you might have concerning this FAQ. Post questions  about this FAQ in the perl forum. Rate this FAQ if you find it helpful or not.

Kevin

Back to Perl FAQ Index
Back to Perl Forum

My Archive

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close