BrowserUk,
I came into this late, but I think using Perl's great 'index' function may give you the desired results. I copied your scripts to get a start, and then used a simple scalar to build the 'Bidirectional lookup' functions. I'm sure they can be improved!
Here goes:
#!/usr/local/bin/myperl
use strict;
use warnings;
use Time::HiRes qw( gettimeofday );
use Devel::Size qw(total_size);
my ( $i, %intByStr, %strByInt, $Both );
$i = 1;
$intByStr{ $_ } = $i++ for 'aaaa' .. 'zzzz';;
$strByInt { $intByStr{ $_ } } = $_ for keys %intByStr;;
print "Hash1: ",total_size( \%intByStr ), "\nHash2: ", total_size(
+ \%strByInt ), "\n";;
our $ksep = chr(253); our $isep = chr(254);
foreach my $key ( keys %intByStr )
{ $Both .= $ksep . $key . $isep . $intByStr{ $key } . "\n";
}
print "\$Both: ",length( $Both ), "\n\n";;
my $testkey = "zabc"; my $testaddr = $intByStr{ $testkey };
my $stime = gettimeofday;
my $tkey = get_key( $testaddr );
print "\tget_key: ", gettimeofday - $stime, " seconds\n";
$stime = gettimeofday;
my $taddr = get_addr( $tkey );
print "\tget_addr: ", gettimeofday - $stime, " seconds\n";
print "\t|$tkey|$taddr|\n";
exit;
sub get_key
{ our( $ksep, $isep );
my $key = shift; my $result;
my $si = index( $Both, "$isep$key\n" );
if ( $si >= 0 )
{ my $sj = rindex ( $Both, $ksep, $si );
if ( $sj >= 0 ) { $result = substr( $Both, $sj+1, $si - ($sj+1
+) ); }
}
return ( $result );
}
sub get_addr
{ our( $ksep, $isep );
my $key = shift; my $result;
my $srch = "$ksep$key$isep"; my $len = length( $srch );
my $si = index( $Both, "$ksep$key$isep" );
if ( $si >= 0 )
{ my $sj = index ( $Both, "\n", $si + $len );
if ( $sj >= 0 ) { $result = substr( $Both, $si+$len, $sj - ($s
+i+$len) ); }
}
return ( $result );
}
1;
__END__
~/tmp:> perl BUKtest.plx
=========================================================
Hash1: 37741336
Hash2: 43113919
$Both: 5829583
get_key: 0.00113105773925781 seconds
get_addr: 0.000988960266113281 seconds
|zabc|439429|
=========================================================
Actual Time using Linux Debian 'time' command w/perl.5.14.2:
real 0m1.591s
user 0m1.560s
sys 0m0.032s
I didn't build my $Both scalar from the raw input, so that I could verify I did it correctly, but $Both doesn't need to be in any order for this to work.
Please note the subs return 'undef' if the key or address is not in $Both. Also I would use 'pack' on the address, but that may or may not save space depending on the actual data supplied.
Regards...Ed
"Well done is better than well said." - Benjamin Franklin