#!/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 | |
by tilly (Archbishop) on Mar 26, 2001 at 17:52 UTC | |
by Corion (Patriarch) on Mar 26, 2001 at 18:14 UTC |