在一列数字中,找到最接近某个目标值的值

2024-02-13

假设我在列中有一些数字数据,例如

11.100000 36.829657 6.101642
11.400000 36.402069 5.731998
11.700000 35.953025 5.372652
12.000000 35.482082 5.023737
12.300000 34.988528 4.685519
12.600000 34.471490 4.358360
12.900000 33.930061 4.042693
13.200000 33.363428 3.738985
13.500000 32.770990 3.447709
13.800000 32.152473 3.169312

我还有一个目标值和一个列索引。给定这组数据,我想在指定索引的列中找到与目标值最接近的值。

例如,如果我的目标值是11.6在列中1,那么脚本应该输出11.7。如果有两个数字与目标值等距,则应输出较大的值。

我感觉 awk 具有执行此操作所需的功能,但任何适用于 bash 脚本的解决方案都是受欢迎的。


尝试这个:

awk -v c=2 -v t=35 'NR==1{d=$c-t;d=d<0?-d:d;v=$c;next}{m=$c-t;m=m<0?-m:m}m<d{d=m;v=$c}END{print v}' file

the -v c=2 and -v t=35可以是动态值。它们是列 idx (c)和你的目标值(t)。在上面的行中,参数是第 2 列和目标 25。它们可以是 shell 变量。

基于给定输入数据的上述行的输出是:

kent$  awk -v c=2 -v t=35 'NR==1{d=$c-t;d=d<0?-d:d;v=$c;next}{m=$c-t;m=m<0?-m:m}m<d{d=m;v=$c}END{print v}' f
34.988528

kent$  awk -v c=1 -v t=11.6 'NR==1{d=$c-t;d=d<0?-d:d;v=$c;next}{m=$c-t;m=m<0?-m:m}m<d{d=m;v=$c}END{print v}' f
11.700000

EDIT

如果有两个数字与目标值等距,则应输出较高的值

上面的代码没有检查这一要求......下面的代码应该可以工作:

awk -v c=1 -v t=11.6 '{a[NR]=$c}END{
        asort(a);d=a[NR]-t;d=d<0?-d:d;v = a[NR]
        for(i=NR-1;i>=1;i--){
                m=a[i]-t;m=m<0?-m:m
                if(m<d){
                    d=m;v=a[i]
                }
        }
        print v
}' file

test:

kent$  awk -v c=1 -v t=11.6 '{a[NR]=$c}END{
        asort(a);d=a[NR]-t;d=d<0?-d:d;v = a[NR]
        for(i=NR-1;i>=1;i--){
                m=a[i]-t;m=m<0?-m:m
                if(m<d){
                    d=m;v=a[i]
                }
        }
        print v
}' f
11.700000

简短的解释。

我不会解释每一行代码及其作用。只是告诉一点做这项工作的想法。

  • 首先读取给定列中的所有元素,保存在数组中
  • 对数组进行排序。
  • 从数组中取出最后一个元素(最大的数字)。将其分配给 varv,并计算它与给定目标之间的差异,将其(绝对值)保存在d
  • 从数组循环的倒数第二个元素到第一个。如果元素和目标之间的差异(绝对值)小于d, 覆盖d使用 diff,还将当前元素保存到v
  • print v,循环后v就是答案。

一些注意事项:

  • 逻辑还有优化的空间。例如我们不必循环遍历整个数组。只是比较d(abs),如果 new diff > d,我们可以停止循环。
  • 由于排序,该算法是O(nlogn)。事实上这个问题可以通过以下方式解决O(n)。如果您的输入数据很大,并且在最坏的情况下(例如您的列的值在范围内)500-99999999999,但你的目标是 1.) 你可能想避免排序。但我认为性能不是你的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在一列数字中,找到最接近某个目标值的值 的相关文章

随机推荐