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

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(使用前将#替换为@)

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

  • 使用 grep 查找包含所有搜索字符串的行

    我有一个文件 其中包含很多与此类似的行 id 2796 some model Profile message type MODEL SAVE fields account 14 address null modification times
  • .profile 无法从 Mac 终端运行

    我有一个 profile 文件 我正在终端中读取并使用别名 但在某些时候 别名由于没有明确的原因而停止工作 其他命令仍在工作 为了快速修复 我删除了 rm 并在用户目录中重新创建了 profile 文件 我可以看到 至少在该目录中没有 ba
  • bash 中 :-(冒号破折号)的用法

    bash中这种风格的含义是什么 PUBLIC INTERFACE eth0 目的是什么 If PUBLIC INTERFACE存在且不为null 则返回其值 否则返回 eth0 实际上有一些记录在bash 手册页 http linux di
  • git 别名中的 AWK 语句

    我正在尝试创建一个 git 别名来以特定格式打印日志中的所有拉取请求 但是 我在使用 AWK 删除双空格时遇到问题 这是使用以下命令的 git log 的输出 git log merges grep pull request pretty
  • grep 两个分隔符之间的子字符串

    我有很多bash使用的脚本perl内的表达式grep为了提取两个分隔符之间的子字符串 例子 echo BeginMiddleEnd grep oP lt Begin End 问题是 当我将这些脚本移植到运行的平台时busybox 融合的 g
  • 迭代 bash 脚本中的变量名称

    我需要在一堆文件上运行一个脚本 这些文件的路径被分配给train1 train2 train20 我想 为什么不使用 bash 脚本使其自动执行呢 所以我做了类似的事情 train1 path to first file train2 pa
  • OSX bash 最小化窗口

    在 Mac 中并使用 bash shell 我想执行一个包含单个命令 启动 Jupyter Lab 的文件并立即最小化终端窗口 有没有办法在不安装第三方软件的情况下做到这一点 是的 只需使用osascript https ss64 com
  • awk/Unix 分组依据

    有这个文本文件 name age joe 42 jim 20 bob 15 mike 24 mike 15 mike 54 bob 21 试图得到这个 计数 joe 1 jim 1 bob 2 mike 3 Thanks awk F NR
  • bash中的用户名、密码程序

    我有一个程序 要求用户输入用户名和密码 然后将其存储在文本文件中 第一列是用户名 第二列是密码 我需要一个命令 在用户输入用户名和新密码时替换密码 如下我拥有的 bin bash admin menu Register User echo
  • 对重复的名称添加双引号

    我想从文件中找到重复的名称 如下所示 并用 标记它们 file James Miki 123 456 7890 Wang Tai 234 563 6879 James Miki 123 456 7890 输出希望看起来像 James Mik
  • sh / Bash shell 脚本中 !# (bang-pound) 的含义是什么?

    我想了解这个 Scala 脚本是如何工作的 usr bin env bash exec scala 0 object HelloWorld def main args Array String println Hello world arg
  • 使用 python 更改目录

    我碰巧发现我无法从 python 代码中更改实际目录 我的测试程序如下 from os import system def sh script system bash c s script sh cd home sh pwd 的输出pwd
  • 如何使用存储在文本文件中的选项在 bash 中显示选择菜单? [复制]

    这个问题在这里已经有答案了 如何使用我存储在文本文件的各行中的选项为用户显示选择菜单 例如 我的文本文件 ingestion txt 如下所示 SOUP FTS CTS JDBC NEW 我希望用户看到这个 Please select an
  • 在 shell 脚本中将一个子字符串替换为另一个字符串

    我有 我爱苏子并结婚 我想将 苏子 更改为 萨拉 firstString I love Suzi and Marry secondString Sara 期望的结果 firstString I love Sara and Marry 要更换
  • 如何在不同目录中启动多个窗口的 tmux?

    我想使用脚本打开一个有 6 个窗口的 tmux 会话 每个窗口位于不同的目录中 我开始于我找到的一个脚本 http blog hawkhost com 2010 07 02 tmux E2 80 93 the terminal multip
  • 如何使用 sed 将空格替换为 \(space)?

    当我使用 sed 将所有空格替换为 X 时 该命令有效 命令为 sed s X g filelist tmp 但是 当我尝试用 space 替换所有出现的空格时 代码是 sed s g filelist tmp 这不起作用 我究竟做错了什么
  • bash循环跳过注释行

    我正在循环文件中的行 我只需要跳过以 开头的行 我怎么做 bin sh while read line do if line doesn t start with then echo line fi done lt tmp myfile 谢
  • awk 的 printf 插入多个变量的正确语法是什么?

    我复制了一些使用 printf 输出字符串在文件中出现的频率的代码 awk BEGIN print The number of times a appears in the file a a counter 1 END printf s n
  • 在复杂的文件夹结构中进行测试

    我正在 golang 中构建一个设计模式存储库 为了运行所有测试 我使用这个 bash 脚本 有用 bin bash go test creational abstract factory go go test creational bui
  • 数组上的 Bash 子字符串扩展

    我有一组带有给定后缀的文件 例如 我有一组带有后缀的pdf文件 pdf 我想使用子字符串扩展来获取不带后缀的文件名 对于单个文件我可以使用 file test pdf echo file 0 4 要对所有文件执行此操作 我现在尝试 file

随机推荐