Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 为每个唯一的$1查找最小的$2_Bash_Perl_Awk_Sed - Fatal编程技术网

Bash 为每个唯一的$1查找最小的$2

Bash 为每个唯一的$1查找最小的$2,bash,perl,awk,sed,Bash,Perl,Awk,Sed,我试图为每1美元的价值获得最小的2美元价值。我的数据如下所示: 0 0 23.9901 13.604 23.9901 13.604 23.9901 3.364 23.9901 3.364 24.054 18.5279 25.0981 17.4839 42.582 0 45.79 0 45.79 15.36 45.7902 12.1518 51.034 12.028 54.11 14.072 54.1102 14.0718 输出必须如下所示: 0 0 23.9901 3.364 24.054 1

我试图为每1美元的价值获得最小的2美元价值。我的数据如下所示:

0 0
23.9901 13.604
23.9901 13.604
23.9901 3.364
23.9901 3.364
24.054 18.5279
25.0981 17.4839
42.582 0
45.79 0
45.79 15.36
45.7902 12.1518
51.034 12.028
54.11 14.072
54.1102 14.0718
输出必须如下所示:

0 0
23.9901 3.364
24.054 18.5279
25.0981 17.4839
42.582 0
45.79 0
45.7902 12.1518
51.034 12.028
54.11 14.072
54.1102 14.0718
我可以通过为每个$1值创建多个文件并在每个文件中查找最小值来管理此操作。但我想知道是否有更优雅的解决方案

谢谢。

您可以这样做:

awk 'NR==1{k=$1;v=$2;next} k==$1 { if (v>$2) v=$2; next} {print k,v; k=$1;v=$2}END{print k,v}'
缩进:

# for the first record store the two fields
NR==1 {
    k=$1
    v=$2
    next
}
# when the first field doesn\'t change
k==$1 {
    # check if the second field is lower
    if (v>$2)
       v=$2
    next
}
{
    # otherwise print stored fields and reinitialize them
    print k,v
    k=$1
    v=$2
}
END {
    print k,v
}'

您可以使用以下gnu awk命令:

awk '!($1 in m) || m[$1]>$2{m[$1]=$2} END{for (i in m) print i, m[i]}' file
或获取与输入文件相同的顺序:

awk 'BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"} !($1 in m) || m[$1] > $2 {m[$1] = $2}
     END{for (i in m) print i, m[i]}' file
BEGIN{PROCINFO[“sorted_in”]=“@ind_num_asc”}
用于按数字索引对关联数组进行排序

输出:

0 0
23.9901 3.364
24.054 18.5279
25.0981 17.4839
42.582 0
45.79 0
45.7902 12.1518
51.034 12.028
54.11 14.072
54.1102 14.0718
在Perl中:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

my %min;

while (<>) {
  chomp;
  my ($key, $value) = split;
  if (!exists $min{$key} or $value < $min{$key}) {
    $min{$key} = $value;
  }
}

for (sort { $a <=> $b } keys %min) {
  say "$_ $min{$_}";
}
#/usr/bin/perl
严格使用;
使用警告;
使用5.010;
我的%min;
而(){
咀嚼;
我的($key,$value)=分割;
如果(!存在$min{$key}或$value<$min{$key}){
$min{$key}=$value;
}
}
对于(排序{$a$b}键%min){
说“$\$min{$\}”;
}
它是作为Unix筛选器编写的,因此它从STDIN读取并写入STDOUT。称之为:

$ ./get_min < input_file > output_file
$./get\u minoutput\u file

使用Gnu或FreeBSD
排序
,您可以按如下操作:

sort -k1,1 -k2,2g file | sort -k1,1g -su
第一个
sort
按第一列和第二列值对文件进行排序。第二个
排序
仅使用第一列来确定唯一性,从而对文件(
-u
)进行唯一性验证。它还使用
-s
标志来确保第二列仍处于有序状态。在这两种情况下,排序在重要时使用
-g
标志(见下文),该标志进行一般数字比较,而Posix标准
-n
标志仅比较前导整数

性能说明:(感谢OP鼓励我进行测量):

-k1,1
中的
g
保留在第一个排序中不是打字错误;它实际上大大加快了排序速度(对于大文件,使用Gnu排序)。标准或整数(
-n
)排序比普通数字排序快得多,可能快10倍。但是,对于“大部分已排序”的文件,所有键类型的速度大约是其两倍。对于或多或少均匀抽样的随机数,字典排序与一般数字排序非常接近;足够接近,结果显示“大部分排序”的加速

在第一次排序中,可以只按第二个字段进行排序:
sort-k2,2g file | sort-k1,1g-su
,但这要慢得多,这是因为第一次排序中的主要排序是普通数字而不是字典,而且第二次排序时文件不再主要排序

这里只有一个示例点,尽管我做了一些测试,结果类似。输入文件由299902行组成,每行包含两个0到1000000范围内的数字,以及三个十进制数字。第一列中正好有100000个不同的数字;每一个在第二列中以不同的数字显示一到五次。(第二列中的所有数字都是不同的。)

所有计时都是用bash的
time
verb收集的,以实际(wallclock)时间为准。(很好地对多线程进行排序,这样用户时间总是更长)

第一列正确排序,第二列随机化:

sort -k1,1  -k2,2g sorted | sort -k1,1g -su          1.24s
sort -k1,1g -k2,2g sorted | sort -k1,1g -su          1.78s
sort        -k2,2g sorted | sort -k1,1g -su          3.00s
sort -k1,1  -k2,2g unsorted | sort -k1,1g -su        1.42s
sort -k1,1g -k2,2g unsorted | sort -k1,1g -su        2.19s
sort        -k2,2g unsorted | sort -k1,1g -su        3.01s
将第一列随机分组:

sort -k1,1  -k2,2g sorted | sort -k1,1g -su          1.24s
sort -k1,1g -k2,2g sorted | sort -k1,1g -su          1.78s
sort        -k2,2g sorted | sort -k1,1g -su          3.00s
sort -k1,1  -k2,2g unsorted | sort -k1,1g -su        1.42s
sort -k1,1g -k2,2g unsorted | sort -k1,1g -su        2.19s
sort        -k2,2g unsorted | sort -k1,1g -su        3.01s

当您想使用sort时,首先必须修复排序。排序将不理解小数点,因此临时更改为a
x

现在对数值字段中的数值进行排序,并将小数点放回原处。 结果列表排序正确,取每个键的第一个值

sed 's/\./ x /g' inputfile | sort -n -k1,3 -k4,6  | sed 's/ x /./g'  | sort -u -k1,1

23.9901的最小值为3.364。相同的$1值是否总是连续的?是的,这是正确的。刚刚修好了$1值总是递增排序。此外,您的示例输出看起来已将
$1
四舍五入到小数点后两位,您的输出中只有
45.79 0
,是否要进行ot处理
45.7902 12.1518
。陛下否您在
54.1102 14.0718
中包含了类似的案例。哦,是的,你忘了在代码中包含你解决问题的尝试。我们可以帮助您修复代码,但S.O.不是免费的编码服务。祝你好运。这是解决这个问题的好方法!但是,对于大数据来说有点慢…@jamie:是的,这种解决方案更适合于第一列尚未排序的情况。我在说明书中遗漏了这一点。