home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / lang / perl / 7606 < prev    next >
Encoding:
Text File  |  1992-12-24  |  2.6 KB  |  75 lines

  1. Newsgroups: comp.lang.perl
  2. Path: sparky!uunet!psinntp!balltown!rodney
  3. From: rodney@cabot.balltown.cma.COM (Rodney Peck)
  4. Subject: Re: Looking for a "numerical/alpha" sort routine.
  5. Message-ID: <1992Dec24.033259.666@cabot.balltown.cma.COM>
  6. Organization: New York State Institute for Sebastian Cabot Studies
  7. References: <1992Dec23.193120.25893@pool.info.sunyit.edu>
  8. Date: Thu, 24 Dec 1992 03:32:59 GMT
  9. Lines: 64
  10.  
  11. buck@pool.info.sunyit.edu (Jesse Buckley) writes:
  12. : Does anyone have a sort/compare routine that will work for numerical
  13. : alpha data?  For example, if I have 1, 2, 3a, 3b, 3c, I want them sorted
  14. : that way.  Right now the <=> compare ignored the letters after the
  15. : numbers.  Thanks.
  16.  
  17. Well, I played with this question for about an hour and came up with this:
  18.  
  19.   $a cmp $b unless $a <=> $b;
  20.  
  21. It's efficient because the cmp is only called if they are numerically
  22. equal.  Otherwise, the value of the numeric compare is returned.
  23.  
  24. Orginally, I spent a lot of time trying to get just the characters and
  25. then compare them with cmp, but since the numbers are equal, the
  26. beginning of the strings will be the same and cmp will properly rank
  27. them even though the numbers are still on the front of the string.
  28.  
  29. However, since I spent all that time working on this, and figured out
  30. a few nifty things that other people might want to study or whatever.
  31.  
  32. Here's the general idea I came up with orginally before trying to
  33. remove the local variables:
  34. sub newcmp {
  35. # works like <=>, but also deals with trailing letters
  36. # use the <=> first, but it lies about things being 
  37. # equal so check with a cmp on the trailing letters
  38.  
  39. local ($ans) = ($a <=> $b);
  40.   if ($ans == 0)
  41.   {
  42.     local($aa, $bb);
  43.     ($aa) = ($a =~ /\d*(\D*)/);
  44.     ($bb) = ($b =~ /\d*(\D*)/);
  45.     $ans = ($aa cmp $bb);
  46.   }
  47.   $ans;
  48. }
  49.  
  50. Here are four different one liners trying to get the letters away
  51. from the numbers before I realized that the numbers would be the same
  52. if the numbers compared equally.  It might be worth someone's while
  53. to read them and figure out the different intentions.  The big thing
  54. was to avoid local variables, and to reduce size.
  55.  
  56.    "$a:$b" =~ /\d*(\D*):\d*(\D*)/, $1 cmp $2 unless $a <=> $b;
  57.  
  58.    @_ = "$a:$b:" =~ /\d(\D):/g, shift cmp shift unless $a <=> $b;
  59.  
  60.    split(/:\d+/,":$a:$b", shift, shift cmp shift unless $a <=> $b;
  61.  
  62.    ($junk,@_) = split(/:\d+/,":$a:$b"), shift cmp shift unless $a <=> $b;
  63.  
  64. And finally, the obJAPH using the new sort routine:
  65.  
  66. #----
  67. #!/bin/perl
  68. $_= '2bn3ap1aj3cr3dl2h 2eh3e 4cc1bu2gr3be4ah';
  69. $_.='4ba4dk2aa4ee2fe1dt2co1cs2dt1e 4fr9a\9bn';
  70. while(($a,$b,$_)=/^(..)(.)(.*)$/) {$a{$a}=$b;}
  71. grep($f.=$a{$_},sort{$a cmp $b unless $a<=>$b}
  72. keys%a);                 eval("print \"$f\"");
  73. #----
  74. Rodney
  75.