For hashes keyed by integer values (positive or negative) represented by 32 bits, returns a list containing the minimum and maximum key values found. Example included in code.
#!/usr/local/bin/perl -w # # A very speedy min/max key finder for hashes keyed by integer values +. # # Requires Perl 5.004 or later, due to the hv_iterkeysv macro. # # Copyright 2000,2001(c) J.C.Wren jcwren@jcwren.com # A production of Twitching Monk Software # No rights reserved, use as you see fit. I'd like to know about it, + though, just for kicks. # use strict; { my %hash = ( 8 => 'eight', 22 => 'twenty-two', 99 => 'ninety-nine', 4 => 'four', 0 => 'zero', -66 => 'negative sixty-six', ); my ($min, $max) = minmaxhash (\%hash); printf ("min key=%d, min key value=%s\n", $min, $hash {$min}); printf ("max key=%d, max key value=%s\n", $max, $hash {$max}); } use Inline C => <<'END_OF_C_CODE'; void minmaxhash (SV* hash_ref) { Inline_Stack_Vars; HV* hash; HE* hash_entry; int i; int num_keys; int temp, min, max; if (!SvROK(hash_ref)) croak("hash_ref is not a reference"); hash = (HV*)SvRV(hash_ref); num_keys = hv_iterinit(hash); for (min = INT_MAX, max = INT_MIN, i = 0; i < num_keys; i++) { /* ** This is a bug: I should be able to eliminate hash_entry ** as a temporary varaible. On my system, the statement ** "if ((temp = SvIV(hv_iterkeysv(hv_iternext(hash)))) > max)" ** causes a segfault. */ hash_entry = hv_iternext(hash); if ((temp = SvIV(hv_iterkeysv(hash_entry))) > max) max = temp; if (temp < min) min = temp; } Inline_Stack_Reset; Inline_Stack_Push(sv_2mortal(newSViv(min))); Inline_Stack_Push(sv_2mortal(newSViv(max))); Inline_Stack_Done; } END_OF_C_CODE

Replies are listed 'Best First'.
Re: Speedy min/max integer key finder for hashes
by Anonymous Monk on Mar 26, 2001 at 11:08 UTC
    Very cool. It's times like this that make me wish I had a C compiler so Inline would work...
      Do you have a little disk space? And some time for a download?

      Then you can have a free C compiler on Windows...

        Recently, I did my first "port" of a Linux program to Win32 (it was a commandline program and it luckily required only a recompile, but I didn't expect that), and while looking for a good package of gcc I found a really nice all-in-one package including gcc and an IDE written in Delphi together with an install program. This makes setting up gcc really easy, and I didn't want to open up yet another front by fighting it out with the gcc installation and makefiles.

        That IDE/compiler bundle is called Dev-C++, and it's available from http://www.bloodshed.net or the mirror at http://www.haikuzone.org. I haven't yet investigated how suited this is for quickly compiling C extensions for Perl, but I'll try this the next time a module wants to install some XS files.

        Of course, the ideal solution is still to compile stuff with VC++, as it has the better code generator and is faster than gcc, but I'll take a second look at Dev-C++ when it comes to easy installation and compatibility with existing Linux sourcecode.