CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
sorting a list with primary and secondery key

 



yaniv_av
Novice

Oct 31, 2002, 2:23 PM

Post #1 of 5 (798 views)
sorting a list with primary and secondery key Can't Post

I have a file with a lot of records with 2 filelds each (line by line).
example:
yaniv : 12
asaf : 44
lui : 09
yaniv : 33
...


I want to sort the file with column 1 as the primary key and column 2 as the secondary key.
How can I do this efficiently ?
(I'm using perl under windows so I can't use the unix-sort-function that working great ...)


jryan
User

Oct 31, 2002, 6:08 PM

Post #2 of 5 (790 views)
Re: [yaniv_av] sorting a list with primary and secondery key [In reply to] Can't Post

 

Code
 
sort {
(split /: /,$a)[0] ne (split /: /,$b)[0] ?
(split /: /,$a)[1] <=> (split /: /,$b)[1] :
$a cmp $b
} @records;



(This post was edited by jryan on Oct 31, 2002, 10:52 PM)


jryan
User

Oct 31, 2002, 6:12 PM

Post #3 of 5 (791 views)
Re: [jryan] sorting a list with primary and secondery key [In reply to] Can't Post

On second thought, this will be more efficient:


Code
sort { 
substr($a,0,rindex($a,":")) ne substr($b,0,rindex($a,":")) ?
substr($a,rindex($a,":")+1)
<=> substr($b,rindex($b,":")+1) :
$a cmp $b
} @records;



(This post was edited by jryan on Nov 4, 2002, 2:29 PM)


Paul
Enthusiast

Nov 1, 2002, 2:29 AM

Post #4 of 5 (778 views)
Re: [jryan] sorting a list with primary and secondery key [In reply to] Can't Post

....and you should use lc() incase there are case differences with your cmp comparison.


davorg
Thaumaturge / Moderator

Nov 3, 2002, 1:00 AM

Post #5 of 5 (767 views)
Re: [yaniv_av] sorting a list with primary and secondery key [In reply to] Can't Post

The obvious approach is something like this:

Code
!/usr/bin/perl 

use strict;
use warnings;

my @data = <DATA>;
chomp @data;

@data = sort {
my @A = split /: /, $a;
my @B = split /: /, $b;

return $A[0] cmp $B[0] or $A[1] <=> $B[1];
} @data;

print map { "$_\n" } @data;

__END__
yaniv : 12
asaf : 44
lui : 09
yaniv : 33

but with a large amount of data that might get a bit inefficient so you should probably consider some kind od Schwartzian Transform.

Code
#!/usr/bin/perl 

use strict;
use warnings;

my @data = <DATA>;
chomp @data;

@data = map { $_->[0] }
sort { $a->[1] cmp $b->[1] or $a->[2] <=> $b->[2] }
map { [ $_, split /: / ] } @data;

print map { "$_\n" } @data;

__END__
yaniv : 12
asaf : 44
lui : 09
yaniv : 33


--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives