Norm Frech <fr...@mwraaa.army.mil>
sub by_the_numbers {
$a - $b;
}
@a = (3,5,7,9,11,13,15,16,14,12,10,8,6,4,2);
@sorta = sort by_the_numbers @a;
print "@sorta\n";
How's that?
print "Just another Perl (book) hacker,"
--
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III |
| mer...@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
The original poster asked about sorting integers so this answer is
right. However, there is a possible trap. I couldn't work out why
@a = (50.1, 50.4, 50.2);
@sorta = sort by_the_numbers @a;
print "@sorta\n";
sometimes didn't work for me (well actually, imagine a LARGE list with
a few |element1 - element2| < 0.5)
"sort" wants integers (<, ==, >) 0 not reals!
Is there a better/stronger/faster "float" comparison function than
sub by_the_numbers { $a > $b ? 1 : $a < $b ? -1 : 0; }
especially if $a and $b are indexes into an associative array?
e.g ... $foo{$a} > $foo{$b} ? ...
Here's an interesting sorter (extracted so my one-liner fits ;-) I
think you can tell that perl is using qsort "as time goes by".
$s=(localtime(time))[0]; sub n { ($a - $b) * $s; }
print grep(s/.*\t//,sort n grep($_=++$i/-50."\t$_",split(/\n*/,<<JAPH)));
,rekcah lreP rehtona tsuJ
JAPH
Andrew
--
Domain address: Andrew....@comp.vuw.ac.nz
Lament: Why do my one-liners never fit in one line? :-(
Wow! A piece of code that really *does* fail based on time-of-day!
(And in Perl... I'm heartbroken. :-)
| Lament: Why do my one-liners never fit in one line? :-(
You don't use long enough lines. :-)
P.S. If you don't see it, think about what happens at 0 seconds into
the minute.
print "Just another Perl [book] hacker,"
Interestingly enuff, I had need for a similar sorting routine today, but with a
twist: I want to sort the indices of an associative array that are of the form
"A0, A1, A2, ..., A9, A10, ..." Of course an alphabetic sort returns "A0, A10,
A11, A19, ..., A1, ...", not what I want!
Any simple solutions? Thanks!
--
Disclaimer: All spelling and/or grammar in this document are guaranteed to be
correct; any exseptions is the is wurk uv intter-net deemuns,.
Mike McManus Mike.M...@FtCollins.NCR.COM, or
NCR Microelectronics ncr-mpd!mik...@ncr-sd.sandiego.ncr.com, or
2001 Danfield Ct. uunet!ncrlnk!ncr-mpd!garage!mikemc
Ft. Collins, Colorado
(303) 223-5100 Ext. 378
Well, two come to mind. The first one is pretty trivial source code:
sub by_the_numbers_mostly { substr($a,1,999) > substr($b,1,999) ? 1 : -1; }
However, I haven't tested this for speed (it's doing a lot of work in
those substr's over and over and over again). What you might want to
do is build a parallel array:
@foo=('A10'..'A19','A0'..'A9'); # not in order, for demo
grep(s/^.//,@fookey = @foo);
sub byfookey { $fookey[$a] > $fookey[$b] ? 1 : -1; }
@sortfoo = @foo[sort byfookey $[..$#foo];
print "@sortfoo";
For large arrays, I believe this would win. For small arrays, the
first would probably win (I haven't tested that... if someone has a
few more minutes than me, go ahead and please let us know).
print "Just another Perl hacker,"
Is this simple enough for the sort function?
sub bynum { substr($a,$[+1,10) > substr($b,$[+1,10); }
--tom
--
"UNIX was never designed to keep people from doing stupid things, because
that policy would also keep them from doing clever things." [Doug Gwyn]
Nope nope nope. I made that same mistake once. Think about
what this returns... either "1" or "0", not "1" or "-1". Arrrgh. :-)
You want something like I already posted involving a test and a 1 or
-1 return.
print pack("c*",(32..127)[42,85,83,84,0,65,78,79,84,72,69,82,0,48,69,82,76,0,72,65,67,75,69,82,12])
I just had the weirdest thought. The ne and != operators should maybe
return -1 or +1 when the operands aren't equal.
Larry
And when Larry has weird thoughts, *I* get to write them down. :-)
Yeah. >>patch29, right? Along with -A, -C, -M filetests and "DATA"
filehandle. Or did you not announce that yet? Oops... too late. :-)
print "Just another Perl [book] hacker,"
Actually, the Berkeley qsort (well let's be precise -- the qsort on
our MORE/bsd 4.3+ boxes running on hp300s) still manages to sort if
you use this comparison routine!
In article <93...@jpl-devvax.JPL.NASA.GOV>, lw...@jpl-devvax.JPL.NASA.GOV
(Larry Wall) writes:
> I just had the weirdest thought. The ne and != operators should maybe
> return -1 or +1 when the operands aren't equal.
>
> Larry
This is a great idea! In conjunction with || returning the last value
evaluated means sort functions can turn into:
sub sort_it { $key1{$a} ne $key1{$b} || -(&fun2{$a} != &fun2{$b}); }
where &fun2() can return floats!
Unfortunately, it will break some of my scripts. E.g
if (($sort_rank != 0) + ($sort_articles != 0) + ($sort_size != 0) > 1) {
print STDERR "$program: only one of -r, -a, -s should be supplied\n";
exit (1);
}
where $sort_* could be -1, 0, +1. But I can fix those.
Possible problems:
+ it looks strange. Take another look at sort_it! Does it sort
things the right way?
+ people will have to re-think how to use comparison operators
because "!=" does not mean "!( == )" E.g negating an
expression (ala De Morgan) will take some thought
+ -(a != b) <=> (-a != -b) which is new!
+ it'll screw up my C programming :-)
I realise it isn't a democracy, but you've got my vote.
Please don't. It will break lots of existing scripts. Moreover, perl
is already wierd enough. I can imagine lots of perl novice users
shifting back to grep/sed/nawk once they discover that != is not the
same anymore as ! == .
I hesitate to say so, but I think this deserves a new built-in
fuction, e.g 'order($a,$b)' and 'lexorder($a,$b)'. The latter can also
take internationalization issues into account, so you can have quick
and dirty string comparisons using eq ne gt ge le lt, and formal
correct (hence a bit slower) using lexorder.
Johan
--
Johan Vromans j...@mh.nl via internet backbones
Multihouse Automatisering bv uucp: ..!{uunet,hp4nl}!mh.nl!jv
Doesburgweg 7, 2803 PL Gouda, The Netherlands phone/fax: +31 1820 62911/62500
------------------------ "Arms are made for hugging" -------------------------
Not necessary. One change should do it (untested, I have neither the space
nor the time to bring up Perl on ncoast):
sub bynum { substr($a,$[+1,10) - substr($b,$[+1,10); }
The -1/+1 idea is interesting, however. (Another doohickey for the Swiss Army
Chainsaw? ;-)
++Brandon
--
Me: Brandon S. Allbery VHF/UHF: KB8JRR/KT on 220, 2m, 440
Internet: all...@NCoast.ORG Delphi: ALLBERY
uunet!usenet.ins.cwru.edu!ncoast!allbery America OnLine: KB8JRR
Call it something else, like "cmp" and "<=>" and I'll take it. I've
had vague yearnings for a comparison operator for a long time.
--
Felix Lee fl...@cs.psu.edu
I like those, much though I loathe 3-character operators. They feel right
and are easy to remember.
While we're redesigning the language, I've been considering another problem.
Subroutines right now have no way to determine what package they were
called from, which makes it difficult to install variables into the correct
package. In addition, the debugger needs to know the file and line number
a routine was called from. I propose a function "caller", which does this:
($package, $file, $line) = caller;
This would be easy to implement--I already keep a pointer to the current
statement, and the current statement contains this info. It would merely
entail making the saved current statement pointer available to the
subroutine.
Other items sneaking in at the last moment. Filetests -M, -A and -C will
return the file's age in days (possibly fractional) at the time the script
started. This will make it much easier to write middle-of-the-night
skulkers.
The tr/// function now has modifier c, d and s. c complements the searchlist,
d deletes any characters in searchlist WITHOUT a replacement in replacementlist,
and s squashes multiple contiguous occurrences of replacementlist characters
to one occurence.
Chip Salzenberg sent me a complete patch to add System V IPC (msg, sem and
shm calls), so I added them. If that bothers you, you can always undefine
them in config.sh. :-)
Lessee... Oh yeah. There's a scalar() pseudo-function call that merely
supplies a scalar context in the middle of a list. I know you can do it
by saying OP . "", but it's better documentation and more efficient. So
you can say things like
local($nextline) = scalar(<STDIN>);
I don't see a need for an operator to supply an array context.
I'm also supplying sysread and syswrite as direct hooks to the read
and write system calls, for those times when you just have to get past
standard I/O.
Some of these aren't even implemented yet, but I know I can get them done
by the time the book comes out... :-)
Holler quick if any of this seems like a tragic mistake. I already listened
to you on <=> and cmp. I'm not unreasonable *all* the time.
Larry
> I just had the weirdest thought. The ne and != operators should maybe
> return -1 or +1 when the operands aren't equal.
>
No, no, please don't do that. It would be very confusing if != and
! == didn't mean the same thing. It would probably break old programs as well.
Besides, such a feature would only be useful in sort sub's (right ?) and
it isn't that hard to write them correctly.
Jan D.
Call it something else, like "cmp" and "<=>" and I'll take it. I've
had vague yearnings for a comparison operator for a long time.
Yeah, that'd be both neat and useful.
Dale Worley Compass, Inc. wor...@compass.com
--
I try to make everyone's day a little more surreal.
Call it something else, like "cmp" and "<=>" and I'll take it. I've
had vague yearnings for a comparison operator for a long time.
Yeah, that'd be both neat and useful.
I sent a note to Larry suggesting this, but here it is again...
Why not "@" for cmp? i.e.
$a @ $b
asks where $a is at in relation to $b. Because the @ is whitespace
delimited and is looking for strings, it doesn't clash with the @array
token.
Why when the script started? Why not their age NOW? That way you could
not only write middle-of-the-night skulkers, but usable Perl daemons to
check for things at intervals.
If the objection is to repeated time() calls, I suggest the tradeoff is
well worth it.
If the objection is nonetheless sustained, how about making the "$NOW"
variable used by -[MAC] modifiable by the programmer.
--
"Just the fax, ma'am." o..oo Tom Neff
-- John McClane .oo.. tn...@bfmny0.BFM.COM
The "at the time of the script" part bothers me a bit; I'd MUCH rather it
were their "instantaneous" age.
When I first saw those operators, I expected them to return a time I could
pass to &ctime(), but instead they give me age. If I want the real time,
I guess I could use (stat(FILE))[9] for mtime and so on. Certainly these
could be easily implemented as subroutines; I'd venture to guess, Larry,
that you consider them common enough operations to make them builtins.
Speaking of such things, I've found myself writing code like this:
if ((stat($tmp))[9] <= (stat($orig))[9]) {
And wishing I could use something like this instead
if ($tmp -nt $orig)
where "-nt" is a binary operator that returns whether the
first operand (either a FILE or a $file) is younger than
the second.
The Korn shell has these three interesting built-in tests:
file1 -nt file2
True if file1 exists and is newer than file2.
file1 -ot file2
True if file1 exists and is older than file2.
file1 -ef file2
True if file1 and file2 exist and refer to the same file.
I would guess the first two compare mtimes and the last
one compares (dev,ino) pairs.
At least the first two seem common enough to be operators.
Anyway, it's trivial to convert between one way and the other via the time
function and a division by 24*60*60...
< If the objection is nonetheless sustained, how about making the "$NOW"
< variable used by -[MAC] modifiable by the programmer.
<
...or by saying "$NOW = time", of course, if Larry decides to implement it
that way.
--
Matthias Urlichs -- url...@smurf.sub.org -- url...@smurf.ira.uka.de
Humboldtstrasse 7 - 7500 Karlsruhe 1 - FRG -- +49+721+621127(Voice)/621227(PEP)