将两个十进制值与perl中的特定范围进行比较

时间:2021-11-03 17:07:53

I am new to Perl. I have two different sets of arrays. Those two arrays having decimal values, both does not have an exact matches, it might be differ only either +0.5 or -0.5. I tried this program, it's not working.

我是Perl的新手。我有两组不同的数组。这两个数组具有十进制值,两者都没有完全匹配,它可能只有+0.5或-0.5不同。我试过这个程序,它不起作用。

@inpt = qw(1003.3965 1036.4392 1037.3843 1045.4459 1101.4259 1107.4253 1118.3928 1191.4904 1320.4855 1420.6291 1440.6921 1562.6698 1742.7587 2084.9137 2248.8761 2337.8865 2628.9931);
@outpt = qw(1191.6017 1101.5336 2629.2865 1742.9336 1036.5726 2338.1574 2249.1057 1440.8222 1440.2074);

foreach $s (@outpt){

    $inc = $s + 0.5;
    $dec = $s - 0.5;

   foreach $p ( @inpt ) {
        if ( $p .. $inc ) {           
            print "$p \t $inc";
        }
        elsif ( $p .. $dec ) {
            print "$p \t $dec";
        }
    }
}

I expected the below output. The @outpt value of 1191.6017 is matching with the range of +0.5 or -0.5 in @inpt value of 1191.4904.

我期待以下输出。 @ initpt值1191.6017与@inpt值1191.4904中的+0.5或-0.5范围匹配。

outpt          inpt
1191.6017     1191.4904
1101.5336     1101.4259
2629.2865     2628.9931
1742.9336     1742.7587
1036.5726     1037.3843
2338.1574     2337.8865
2249.1057     2248.8761
1440.8222     1440.6291
1440.2074     1440.6291

3 个解决方案

#1


try this:

use strict;
use warnings;

my $limit = 0.5;
my $result = "";

my @inpt = qw(1003.3965 1036.4392 1037.3843 1045.4459 1101.4259 1107.4253 1118.3928 1191.4904 1320.4855 1420.6291 1440.6921 1562.6698 1742.7587 2084.9137 2248.8761 2337.8865 2628.9931);
my @outpt = qw(1191.6017 1101.5336 2629.2865 1742.9336 1036.5726 2338.1574 2249.1057 1440.8222 1440.2074);

foreach my $s (@outpt){
   foreach my $t (@inpt) {
      if($s >= $t - $limit && $s <= $t + $limit) {
          $result .= "$s \t $t\n";
      }
   }
}     
print $result;

#2


my $limit = 0.5;

my @inpt = qw(1003.3965 1036.4392 1037.3843 1045.4459 1101.4259 1107.4253 1118.3928 1191.4904 1320.4855 1420.6291 1440.6921 1562.6698 1742.7587 2084.9137 2248.8761 2337.8865 2628.9931);
my @outpt = qw(1191.6017 1101.5336 2629.2865 1742.9336 1036.5726 2338.1574 2249.1057 1440.8222 1440.2074);

my @result = map {
  my $p = $_;
  map { "$p \t $_" } grep { abs($p-$_) <= $limit } @inpt;
  # without grep
  # map { abs($p-$_) <= $limit ? "$p \t $_" : () } @inpt;
} @outpt;

print $_, "\n" for @result;

output

1191.6017    1191.4904
1101.5336    1101.4259
2629.2865    2628.9931
1742.9336    1742.7587
1036.5726    1036.4392
2338.1574    2337.8865
2249.1057    2248.8761
1440.8222    1440.6921
1440.2074    1440.6921

#3


The nmin_by function from the List::UtilsBy is very useful for something like this. It allows you to find the value in a list that provides the smallest value when a given function is applied to it. If I use the absolute difference from the current element of @outpt then I can find the closest number in the @inpt list

List :: UtilsBy中的nmin_by函数对于这样的事情非常有用。它允许您在列表中查找值,该值在应用给定函数时提供最小值。如果我使用@outpt当前元素的绝对差值,那么我可以在@inpt列表中找到最接近的数字

It would look like this

它看起来像这样

use strict;
use warnings;

use List::UtilsBy 'nmin_by';

my @inpt = (
  1003.3965, 1036.4392, 1037.3843, 1045.4459, 1101.4259,
  1107.4253, 1118.3928, 1191.4904, 1320.4855, 1420.6291,
  1440.6921, 1562.6698, 1742.7587, 2084.9137, 2248.8761,
  2337.8865, 2628.9931,
);
my @outpt = (
  1191.6017, 1101.5336, 2629.2865, 1742.9336, 1036.5726,
  2338.1574, 2249.1057, 1440.8222, 1440.2074,
);

printf "%-9s      %-9s\n", qw/ outpt inpt /;

for my $out ( @outpt ) {
  my $inp = nmin_by { abs($out - $_) } @inpt;
  printf "%9.4f      %9.4f\n", $out, $inp;
}

output

outpt          inpt     
1191.6017      1191.4904
1101.5336      1101.4259
2629.2865      2628.9931
1742.9336      1742.7587
1036.5726      1036.4392
2338.1574      2337.8865
2249.1057      2248.8761
1440.8222      1440.6921
1440.2074      1440.6921

#1


try this:

use strict;
use warnings;

my $limit = 0.5;
my $result = "";

my @inpt = qw(1003.3965 1036.4392 1037.3843 1045.4459 1101.4259 1107.4253 1118.3928 1191.4904 1320.4855 1420.6291 1440.6921 1562.6698 1742.7587 2084.9137 2248.8761 2337.8865 2628.9931);
my @outpt = qw(1191.6017 1101.5336 2629.2865 1742.9336 1036.5726 2338.1574 2249.1057 1440.8222 1440.2074);

foreach my $s (@outpt){
   foreach my $t (@inpt) {
      if($s >= $t - $limit && $s <= $t + $limit) {
          $result .= "$s \t $t\n";
      }
   }
}     
print $result;

#2


my $limit = 0.5;

my @inpt = qw(1003.3965 1036.4392 1037.3843 1045.4459 1101.4259 1107.4253 1118.3928 1191.4904 1320.4855 1420.6291 1440.6921 1562.6698 1742.7587 2084.9137 2248.8761 2337.8865 2628.9931);
my @outpt = qw(1191.6017 1101.5336 2629.2865 1742.9336 1036.5726 2338.1574 2249.1057 1440.8222 1440.2074);

my @result = map {
  my $p = $_;
  map { "$p \t $_" } grep { abs($p-$_) <= $limit } @inpt;
  # without grep
  # map { abs($p-$_) <= $limit ? "$p \t $_" : () } @inpt;
} @outpt;

print $_, "\n" for @result;

output

1191.6017    1191.4904
1101.5336    1101.4259
2629.2865    2628.9931
1742.9336    1742.7587
1036.5726    1036.4392
2338.1574    2337.8865
2249.1057    2248.8761
1440.8222    1440.6921
1440.2074    1440.6921

#3


The nmin_by function from the List::UtilsBy is very useful for something like this. It allows you to find the value in a list that provides the smallest value when a given function is applied to it. If I use the absolute difference from the current element of @outpt then I can find the closest number in the @inpt list

List :: UtilsBy中的nmin_by函数对于这样的事情非常有用。它允许您在列表中查找值,该值在应用给定函数时提供最小值。如果我使用@outpt当前元素的绝对差值,那么我可以在@inpt列表中找到最接近的数字

It would look like this

它看起来像这样

use strict;
use warnings;

use List::UtilsBy 'nmin_by';

my @inpt = (
  1003.3965, 1036.4392, 1037.3843, 1045.4459, 1101.4259,
  1107.4253, 1118.3928, 1191.4904, 1320.4855, 1420.6291,
  1440.6921, 1562.6698, 1742.7587, 2084.9137, 2248.8761,
  2337.8865, 2628.9931,
);
my @outpt = (
  1191.6017, 1101.5336, 2629.2865, 1742.9336, 1036.5726,
  2338.1574, 2249.1057, 1440.8222, 1440.2074,
);

printf "%-9s      %-9s\n", qw/ outpt inpt /;

for my $out ( @outpt ) {
  my $inp = nmin_by { abs($out - $_) } @inpt;
  printf "%9.4f      %9.4f\n", $out, $inp;
}

output

outpt          inpt     
1191.6017      1191.4904
1101.5336      1101.4259
2629.2865      2628.9931
1742.9336      1742.7587
1036.5726      1036.4392
2338.1574      2337.8865
2249.1057      2248.8761
1440.8222      1440.6921
1440.2074      1440.6921