Xref: utzoo comp.unix.shell:2190 comp.lang.perl:5310 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!ucbvax!iwarp.intel.com!news From: merlyn@iwarp.intel.com (Randal L. Schwartz) Newsgroups: comp.unix.shell,comp.lang.perl Subject: Re: How to sort on right most column Summary: WATCH THE FOLLOWUP. IF IT'S NOT PERL, REMOVE COMP.LANG.PERL Message-ID: <1991May15.162442.10206@iwarp.intel.com> Date: 15 May 91 16:24:42 GMT References: <13320@exodus.Eng.Sun.COM> Sender: news@iwarp.intel.com Reply-To: merlyn@iwarp.intel.com (Randal L. Schwartz) Organization: Stonehenge; netaccess via Intel, Beaverton, Oregon, USA Lines: 82 In-Reply-To: rock@warp.Eng.Sun.COM (Bill Petro) In article <13320@exodus.Eng.Sun.COM>, rock@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@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/