How to sort on right most column

Randal L. Schwartz merlyn at iwarp.intel.com
Thu May 16 02:24:42 AEST 1991


In article <13320 at exodus.Eng.Sun.COM>, rock at warp (Bill Petro) writes:
| I have the following data in this format - I want to sort it on the
| right most column.  The columns are not tab delimited, and some of the
| columns have arbitrary numbers of words (specifically the third column
| from the left, column c).  Sort assumes that you start numbering on the
| left, and count from 0.  How would you start with the right most
| column, column e?
| 
|   0    1   2                              3                     4
| 
|   a    b   c                              c                     e
| 
|  FOO  BAR ACE CORPORATION                SUNNYVALE              2.00
|  FOO  BAR ACER COMPUTED COMPANY          MILPITAS              20.00
|  FOO  BAR APOLLO COMPUTER, INC.          CHELMSFORD             1.00
|  FOO  BAR APPLE COMPUTER, INC.           CUPERTINO              8.00
|  FOO  BAR BOEING                         TUKWILA               53.00
|  FOO  BAR BOEING COMPUTER SERVICES       EDDYSTONE              2.00
|  FOO  BAR CITIBANK N. A.                 ANDOVER                4.00
|  FOO  BAR CITIBANK NORTH AMERICA         LONG ISLAND CITY      26.00

Well, here's a terribly inefficient one, good enough for small amounts
of data:

##################################################
#!/usr/bin/perl

sub bylastcol {
	@a = split(/\s+/, $a);
	@b = split(/\s+/, $b);
	pop(@a) <=> pop(@b);
}

print sort bylastcol <>;
##################################################

This is inefficient because the "last column" is computed and
recomputed over and over again on each compare.  A better way would be
to compute it once and cache it:

##################################################
#!/usr/bin/perl

sub once {
	return $n if defined($n = $once{$_[0]});
	@a = split(/\s+/, $_[0]);
	$once{$_[0]} = pop(@a);
}


sub bylastcol {
	&once($a) <=> once($b);
}

print sort bylastcol <>;
##################################################

An even better way requires the cooperation of the calling routine to
make a normal array, rather than an associative array, as in:

##################################################
#!/usr/bin/perl

sub byaux {
	$aux[$a] <=> $aux[$b];
}

@data = <>;
for (@data) {
	@a = split(/\s+/, $_);
	push(@aux, pop(@a));
}

print @data[sort byaux $[..$#data];
##################################################

print "Just another Perl hacker,"
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn at iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/



More information about the Comp.unix.shell mailing list