in reply to better way to printing random hash key and its value
If you find yourself pulling out a rubber stamp then it is time to either use a subroutine or a data structure. In this case the key parts of the solution are to concatenate the ranges used for partitioning into an array and put the result of the partitioning into an array.
#!/usr/bin/perl use strict; use warnings; my %netHash; my @capVals; my @limits = (1.0, 1.4, 1.9, 2.4, 3.0, 3.5, 4.0); while(<DATA>) { chomp; my($nx,$ny) = split; $netHash{$nx} = $ny if ($ny > 1); } foreach my $key (keys %netHash) { my $value = $netHash{$key}; my $index = BinSearch ($value, sub {$_[0] <=> $_[1]}, \@limits); next if $index < 0; $capVals[$index]{$key} = $value; } printHash ($_) for @capVals; sub printHash { my $href = shift; return if ! defined $href; my $RandKey = (keys %{$href}) [int(rand(scalar (keys %{$href})))]; print "$RandKey $href->{$RandKey}\n"; } sub BinSearch { my ($target, $cmp, $array) = @_; my $posmin = 0; my $posmax = $#$array; return undef if ! @$array; return -0.5 if $cmp->($array->[0], $target) > 0; return $#$array + 0.5 if $cmp->($array->[-1], $target) < 0; while (1) { my $mid = int (($posmin + $posmax) / 2); my $result = $cmp->($array->[$mid], $target); if ($result < 0) { $posmin = $posmax, next if $mid == $posmin && $posmax != $ +posmin; return $mid + 0.5 if $mid == $posmin; $posmin = $mid; } elsif ($result > 0) { $posmax = $posmin, next if $mid == $posmax && $posmax != $ +posmin; return $mid - 0.5 if $mid == $posmax; $posmax = $mid; } else { return $mid; } } } __DATA__ k1 0.2 k2 0.9 k3 1 k4 1.2 k5 1.3 k6 2 k7 2.2 k8 2.7 k9 2.76 k10 3.001 k11 3.12 k12 3.2 k14 3.22 k15 3.3 k16 3.34 k17 3.4 k18 3.62 k19 3.8 k20 3.89
Prints:
k4 1.2 k7 2.2 k9 2.76 k11 3.12 k19 3.8
This code assumes that there are not supposed to be gaps between the partitioned ranges. Upper and lower limit pairs would need to be stored and the search modified if the ranges truely are gappy.
|
|---|