如何计算每个唯一条目的最大值和最小值

如何计算每个唯一条目的最大值和最小值

我需要找到文件中每个条目的最大值和最小值:

#subset of my file
NEUTRON   20.900103
PION-      0.215176
PION-     22.716532
NEUTRON    8.043279
PION+      1.374297
PION-      0.313350
PION+      0.167848

当有多个条目名称时,如何循环遍历文件并找到每个名称的最小值和最大值。我已经使用 awk 来计算每个条目并且没有重复,但是每个名称的每个重复都包含一个数字,而该数字就是我试图过滤掉每个条目的最大值和最小值的数字。整个文件的 ex 输出:

Name         Count     Minimum        Maximum        
--------     -----     ---------      ---------      
KAON-            1      5.489958       5.489958      
NEUTRON          2      8.043279      20.900103      
PHOTON          10      0.034664       1.897264       
PION-            5      0.192247      22.716532       
PION+            7      0.167848       7.631051       
PROTON           1      1.160216       1.160216       

答案1

awk '{
  count[$1]++
  min[$1]=(!($1 in min) || $2<min[$1]) ? $2 : min[$1]
  max[$1]=(!($1 in max) || $2>max[$1]) ? $2 : max[$1]
}
END {
  print "Name","Count","Minimum","Maximum"
  print "----","-----","-------","-------"
  for(i in count) print i,count[i],min[i],max[i]
}' file | column -t

最小数组值赋值的逻辑是:
如果第一个字段的名称在数组中不存在 ( !($1 in min)) 或 ( ||) 第二个字段小于当前数组值 ( $2<min[$1]),则 ( ?) 分配新值$2, else( :) 指定旧值min[$1]

用于| column -t将结果漂亮地打印为表格。如果您不需要它,可以将其删除。

输出:

Name     Count  Minimum   Maximum
----     -----  -------   -------
PION+    2      0.167848  1.374297
PION-    3      0.215176  22.716532
NEUTRON  2      8.043279  20.900103

答案2

正如 Jeff Schaller 所指出的,bash 不是一个文本处理器,尽管您所要求的实现并不是特别困难。所以这里有一种方法可以做到这一点......无论它的价值如何。

$ awk '!/^#.*/ {
      ((++cnt[$1])); 
      if (cnt[$1]==1) 
          {min[$1]=max[$1]=$2} 
      else if ($2 < min[$1]) 
          { min[$1]=$2} 
      else if ($2 > max[$1]) 
          {max[$1]=$2}
      } 
      END {
          printf "%-10s%7s%10s%12s\n","Name","Count","Minimum", "Maximum";
          for (i in cnt) 
              printf "%-10s%7d%10.6g%12.8g\n", i,cnt[i],min[i],max[i];
          }' testdata 

输出:

Name        Count   Minimum     Maximum
PION+           2  0.167848    1.374297
PION-           3  0.215176   22.716532
NEUTRON         2   8.04328   20.900103

解释:

  • 跳过以 a 开头的任何行(记录)#
  • awk对于每个记录,在程序执行开始时从 0 开始将 cnt[$1] 加 1
  • 如果当前记录的第一个字段值“$1”以前从未见过,则将该值的最小值和最大值初始化为值“$2”。
  • 在其他情况下(当在之前的记录中至少看到一次值“$1”时),更新最小值和最大值
  • 最后使用格式化打印以尊重 OP 中示例输出的方面。

相关内容