Click here to get back home

Numerically sort a file on a given column where column is a $var

 HomeNewsGroups | Search | About
 comp.lang.perl.misc    Post an article   get this group's latest topics as an RSS feed add this group's latest topics to your My MSN content add this group's latest topics to your My Yahoo content
Subject Author Date
Numerically sort a file on a given column where column is a $var joemacbusiness 07-17-2008
Posted by joemacbusiness on July 17, 2008, 5:29 pm
Please log in for more thread options
Hi All,

I want a subroutine that will sort a file on any given column.
So I have a file like this:

300 400 500 600 700
33 2337483 482 78374 4567
10 20 30 40 50
1000 1001 1002 1003 1004
9 8 7 6 5

And I run my numericSortCol() routine on it sorting on
column 1 and should get this:

9 8 7 6 5
10 20 30 40 50
300 400 500 600 700
1000 1001 1002 1003 1004
33 2337483 482 78374 4567

The problem is that I cannot get the bynum() to accept 2 args.
The code will work if I hard-code the $col in bynum, and
tweek the "problem line" a bit but that defeats the purpose of the
"sort on column" feature.

Does anyone have a solution for this?

Thanks, --Joe M.

######################### Here's the code I have so far:
[joe@localhost work]$ cat test18.pl
#!/usr/bin/perl

my $infile = "test18.in";
open(F,"$infile") || print "cannot open $infile $!";
my @array = <F>;
close(F);

numericSortCol(1,\@array);

sub numericSortCol {
my $col = shift;
my $aref = shift;
foreach my $item (sort bynum($col,@{ $aref })){ # <<<< problem
line??
print "item: $item\n";
}
}

sub bynum {
my $col = shift;
@a = split(/\s+/,$a);
@b = split(/\s+/,$b);
$a[$col] <=> $b[$col];
# $a[1] <=> $b[1];
}
[joe@localhost work]$
[joe@localhost work]$
######################### Here's the input file
[joe@localhost work]$ cat test18.in
300 400 500 600 700
33 2337483 482 78374 4567
10 20 30 40 50
1000 1001 1002 1003 1004
9 8 7 6 5
[joe@localhost work]$
[joe@localhost work]$
######################### Here's the runtime:
[joe@localhost work]$ perl test18.pl
item: 1
item: 9 8 7 6 5

item: 10 20 30 40 50

item: 33 2337483 482 78374 4567

item: 300 400 500 600 700

item: 1000 1001 1002 1003 1004

[joe@localhost work]$


Posted by sln on July 17, 2008, 6:49 pm
Please log in for more thread options
On Thu, 17 Jul 2008 14:29:52 -0700 (PDT), joemacbusiness@yahoo.com wrote:

>Hi All,
>
>I want a subroutine that will sort a file on any given column.

Maybe your just in a rush, but I stopped reading here, when I read "sort a file"

sln

Posted by Uri Guttman on July 17, 2008, 8:41 pm
Please log in for more thread options

j> The problem is that I cannot get the bynum() to accept 2 args.
j> The code will work if I hard-code the $col in bynum, and
j> tweek the "problem line" a bit but that defeats the purpose of the
j> "sort on column" feature.

j> open(F,"$infile") || print "cannot open $infile $!";

useless use of quotes on a scalar. not needed and it can be a bug.

j> my @array = <F>;
j> close(F);

use File::Slurp ;
my @data = read_file( $infile ) ;

j> numericSortCol(1,\@array);

j> sub numericSortCol {
j> my $col = shift;
j> my $aref = shift;
j> foreach my $item (sort bynum($col,@{ $aref })){ # <<<< problem
j> line??

well, that isn't how perl's sort works. it can take a sub name (you have
a sub call) or a code block.


and you should look at Sort::Maker which can do this for you
easily. just create a simple expression to get the column you want based
on $_. that could be something like:

        (split( ' ', $_))[$col]

the rest i leave as an exercise.

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------

Posted by Jens Thoms Toerring on July 17, 2008, 9:04 pm
Please log in for more thread options
joemacbusiness@yahoo.com wrote:
> Hi All,

> I want a subroutine that will sort a file on any given column.
> So I have a file like this:

> 300 400 500 600 700
> 33 2337483 482 78374 4567
> 10 20 30 40 50
> 1000 1001 1002 1003 1004
> 9 8 7 6 5

> And I run my numericSortCol() routine on it sorting on
> column 1 and should get this:

> 9 8 7 6 5
> 10 20 30 40 50
> 300 400 500 600 700
> 1000 1001 1002 1003 1004
> 33 2337483 482 78374 4567

> The problem is that I cannot get the bynum() to accept 2 args.
> The code will work if I hard-code the $col in bynum, and
> tweek the "problem line" a bit but that defeats the purpose of the
> "sort on column" feature.

> ######################### Here's the code I have so far:
> [joe@localhost work]$ cat test18.pl
> #!/usr/bin/perl

> my $infile = "test18.in";
> open(F,"$infile") || print "cannot open $infile $!";
> my @array = <F>;
> close(F);

> numericSortCol(1,\@array);

> sub numericSortCol {
> my $col = shift;
> my $aref = shift;
> foreach my $item (sort bynum($col,@{ $aref })){ # <<<< problem
> line??

Look again at the documentation for the sort function. It takes
either a block or a function (that itself expects two arguments)
and, as the second argument, a list to be sorted. Your use of
sort doesn't seem to fit that very well and I guess if you had
used 'use warnings;' you would have been told so...

> print "item: $item\n";
> }
> }

> sub bynum {
> my $col = shift;
> @a = split(/\s+/,$a);
> @b = split(/\s+/,$b);
> $a[$col] <=> $b[$col];
> }

The simplest solution is probaly not to use a function name when
calling sort but instead a block like this:

#!/usr/bin/perl

use strict;
use warnings;

my @array = <DATA>;
numericSortCol( 1, \@array );

sub numericSortCol {
my ( $col, $aref ) = @_;

print "item: $_"
for sort { ( split /\s+/, $a )[ $col ] <=>
( split /\s+/, $b )[ $col ] } @$aref;
}

__DATA__
300 400 500 600 700
33 2337483 482 78374 4567
10 20 30 40 50
1000 1001 1002 1003 1004
9 8 7 6 5
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de

Posted by Ted Zlatanov on July 18, 2008, 9:48 am
Please log in for more thread options
On Thu, 17 Jul 2008 14:29:52 -0700 (PDT) joemacbusiness@yahoo.com wrote:

j> I want a subroutine that will sort a file on any given column.
j> So I have a file like this:

j> 300 400 500 600 700
j> 33 2337483 482 78374 4567
j> 10 20 30 40 50
j> 1000 1001 1002 1003 1004
j> 9 8 7 6 5

j> And I run my numericSortCol() routine on it sorting on
j> column 1 and should get this:

j> 9 8 7 6 5
j> 10 20 30 40 50
j> 300 400 500 600 700
j> 1000 1001 1002 1003 1004
j> 33 2337483 482 78374 4567

Use the standard Unix utility `sort':

sort -n +1 FILE
(use "-k 1" instead of +1 if GNU sort is installed)

e.g. sort /etc/passwd by user ID:

sort -t: -n +2 /etc/passwd

Read the docs for `sort' for further information.

You can use Perl for this (as others have shown), but if all you want is
to sort a file by a simple key, `sort' will do just fine. It's also
likely to be much faster in most circumstances.

Ted

Similar ThreadsPosted
Find Missing Column and Extra Column March 12, 2007, 6:31 am
need help on cgi to get multi pages and could sort by column from Oracle March 27, 2008, 1:55 am
Counting column delimiters per row in a text file February 8, 2005, 10:52 am
order a semicolon-separated data file by a value of a column September 22, 2004, 10:06 pm
Sort keys in a hash numerically August 8, 2006, 4:20 pm
How to get the column name in a spreadsheet app? August 8, 2006, 5:51 am
awk - or how to select a column in perl December 14, 2005, 4:22 pm
Column extraction in perl September 15, 2006, 12:31 pm
extract a column from 2 dimensional array September 13, 2004, 7:31 am
Sum the middle column for a given unique volser. September 15, 2006, 2:28 pm

Our other projects:

Art Dolls, Fairies and Mermaids - Sunnyfaces.net

Roy's Linux, Programming and Search Engines messages

1-Script XML SitemapXML Sitemap