Assuming that you mean that you want $size elements either side of where the $target would be in the sorted array, then using a binary search (binary chop) to locate the appropriate position will be about your quickest method. Something along the lines of this:
Updated: Slightly better test data generation.
#! perl -slw
use strict;
our $TARGET ||= 4;
our $SIZE ||= 2;
our $N ||= 10;
sub binaryChop{
my( $aref, $target ) = @_;
my( $lo, $hi, $mid ) = ( 0, $#$aref );
while( $lo < $hi ) {
$mid = ( $hi + $lo ) / 2;
if( $aref->[ $mid ] > $target ) {
$hi = $mid - 1;
}
elsif( $aref->[ $mid ] < $target ) {
$lo = $mid + 1;
}
else {
return $mid;
}
}
return $lo;
}
my @data = grep{ $_ != $TARGET } 1 .. $N;
my $targetIndex = binaryChop( \@data, $TARGET );
print "@data";
print join ', ', @data[ $targetIndex - $SIZE .. $targetIndex + $SIZE -
+ 1 ];
__END__
C:\test>566908 -N=20 -TARGET=8 -SIZE=2
1 2 3 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20
6, 7, 9, 10
C:\test>566908 -N=20 -TARGET=8 -SIZE=2
1 2 3 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20
6, 7, 9, 10
C:\test>566908 -N=20 -TARGET=8 -SIZE=2
1 2 3 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20
6, 7, 9, 10
C:\test>566908 -N=20 -TARGET=8 -SIZE=3
1 2 3 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20
5, 6, 7, 9, 10, 11
C:\test>566908 -N=20 -TARGET=8 -SIZE=4
1 2 3 4 5 6 7 9 10 11 12 13 14 15 16 17 18 19 20
4, 5, 6, 7, 9, 10, 11, 12
C:\test>566908 -N=20 -TARGET=11 -SIZE=4
1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20
7, 8, 9, 10, 12, 13, 14, 15
C:\test>566908 -N=20 -TARGET=11 -SIZE=1
1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20
10, 12
C:\test>566908 -N=2000 -TARGET=1111 -SIZE=3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 ...
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 ...
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 ...
22 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 10 ..
23 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 12 ..
23 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 14 ..
23 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 16 ..
23 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 18 ..
1107, 1108, 1109, 1110, 1112, 1113
Note that my test data generation is simplistic (allows duplicates; allows the target value), and the math selecting the appropriate slice of the data to pick may need adjusting to suit your requirements.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
|