in reply to Better mousetrap (getting top N values from list X)
As the benchmarks show, your algorithm, is a good one. With a few tweaks to the implementation it runs faster still:
sub top_x { my( $n, $aref ) = @_; my @topN = (0)x$n--; for my $val ( @$aref ) { next if $topN[ $n ] > $val; $topN[ $_ ] < $val and splice( @topN, $_, 0, $val ), last for 0 .. $n; } return @topN[ 0 .. $n ]; }
If this is more than an intellectual exercise, and you can handle Inline::C, then the same algorithm C-ified really flies:
Update: Correct the Inline::C implementation below to avoid calloc and allow me to free the temporary C array.
void topN( int n, AV*data ) { int *topN; int len = av_len( data ); int i, j, k; Inline_Stack_Vars; Newz( 1, topN, n + 1, int ); for( i = 0; i <= len; i++ ) { int val = SvIV( *av_fetch( data, i, 0 ) ); for( j = 0; j < n; j++ ) { if( topN[ j ] > val ) continue; if( topN[ j ] < val ) { for( k = n; k > j; k-- ) topN[ k ] = topN[ k-1 ]; topN[ j ] = val; break; } } } Inline_Stack_Reset; for( i = 0; i < n; i++ ) Inline_Stack_Push( sv_2mortal( newSViv( topN[ i ] ) ) ); Safefree( topN ); Inline_Stack_Done; }
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: Better mousetrap (getting top N values from list X)
by Limbic~Region (Chancellor) on Feb 02, 2005 at 13:49 UTC | |
by BrowserUk (Patriarch) on Feb 02, 2005 at 18:04 UTC |