in reply to How to print the 10 most recent (epoch) keys in a hash when epoch is not the key

Simple way to get all the hash keys in epoch sorted order:

my @keys_in_epoch_order = map { $$_[1] } # isolate key sort { $$b[0] <=> $$a[0] } # sort by epoch numerical +descending map { [ $out_hash{$_}{EPOCH}, $_ ] } # arrays of epoch, key keys %out_hash; # source keys
  • Comment on Re: How to print the 10 most recent (epoch) keys in a hash when epoch is not the key
  • Download Code

Replies are listed 'Best First'.
Re^2: How to print the 10 most recent (epoch) keys in a hash when epoch is not the key
by johngg (Canon) on Nov 29, 2009 at 00:29 UTC
    Simple way to get all the hash keys in epoch sorted order:

    Not quite simple enough! You don't need the added complication of a Schwartzian transform here as the item you are sorting on is already available rather than being obtained via some expensive transaction. Here a ST only slows things down.

    In the following two benchmarks we are sorting files by their epoch modification date. In the first we have a hash of files as key and their epoch modification times as value which are sorted both via direct hash lookup and via a ST. Note how the ST is slower.

    use strict; use warnings; use File::Find; use Benchmark qw { cmpthese }; my %files = (); my $rcWanted = sub { $files{ $File::Find::name } = ( lstat $File::Find::name )[ 9 ]; }; find( $rcWanted, q{/usr/bin} ); cmpthese( -5, { Direct => sub { my $raSorted = useDirect() }, ST => sub { my $raSorted = useST() }, } ); sub useDirect { my @sorted = sort { $files{ $b } <=> $files{ $a } } keys %files; return \ @sorted; } sub useST { my @sorted = map { $_->[ 0 ] } sort { $b->[ 1 ] <=> $a->[ 1 ] } map { [ $_, $files{ $_ } ] } keys %files; return \ @sorted; }

    The output.

    Rate ST Direct ST 35.8/s -- -37% Direct 56.9/s 59% --

    If we now change the code for the second benchmark so that we just have an array of filenames, we have to do the "expensive" inode look-up to get the modification time as part of the sort code. Now the ST makes sense as it avoids the repetitive lstat calls for each file as the sort algorithm moves the file into its correct position.

    use strict; use warnings; use File::Find; use Benchmark qw { cmpthese }; my @files = (); my $rcWanted = sub { push @files, $File::Find::name; }; find( $rcWanted, q{/usr/bin} ); cmpthese( -5, { Direct => sub { my $raSorted = useDirect() }, ST => sub { my $raSorted = useST() }, } ); sub useDirect { my @sorted = sort { lstat( $b ) <=> lstat( $a ) } @files; return \ @sorted; } sub useST { my @sorted = map { $_->[ 0 ] } sort { $b->[ 1 ] <=> $a->[ 1 ] } map { [ $_, lstat( $_ ) ] } @files; return \ @sorted; }

    The output.

    Rate Direct ST Direct 1.29/s -- -46% ST 2.38/s 85% --

    I hope this is of interest.

    Cheers,

    JohnGG

Re^2: How to print the 10 most recent (epoch) keys in a hash when epoch is not the key
by kevyt (Scribe) on Nov 28, 2009 at 15:09 UTC

    I thought about joining the 3 values into a string and then pushing them onto an array but I would need something to join/split the values that could never be found on a webpage. Example:

    #To store the values $str = $epoch . "SpLiTvAlUe" . $url . ""SpLiTvAlUe" . $desc; # To print the values unshift (@array, $str); if (@array > 10){ pop(@array) } foreach (@array){ my ($epoch, $url, $desc)= split (/\"SpLiTvAlUe\"/); print $epoch . " " . $url . " " . $desc . "\n"; }
    I have not tried it and I don't like my splitting value but this might work?
Re^2: How to print the 10 most recent (epoch) keys in a hash when epoch is not the key
by kevyt (Scribe) on Nov 28, 2009 at 15:35 UTC
    Thanks