首页 > 学技术 > 技术网文 > Linux Shell > 正文

[精彩] 找出最小值的问题?


来源 chinaunix.net 酷勤网整理

1 10
2 9
3 10
4 11
5 10
6 9
7 11
8 10
9 11
10 10
11 8
12 7
13 5
14 3
15 0
16 1
17 2
18 4
19 5
20 7
21 9
22 10
23 11
24 10
25 11

第2列 数据值 大致  是开始下降,然后增加的一个变化趋势!

所以希望:
找出最小值 ,并且 在最小值的后面数据,找出第一个  比最小值 大于3 的数据   的位置!



 mocou 回复于:2005-06-10 23:45:16

偶是找出最小值大4的数
引用:# cat file
1 10 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 1 
17 2 
18 4 
19 5 
20 7 
21 9 
22 10 
23 11 
24 10 
25 11



结果

# ./scripts
0 18


# cat scripts

aa=$(awk 'BEGIN{temp=0;}{if($2<temp){temp=$2;}}END{aa=$temp;print temp;}' file)
bb=$(awk '/'"\<$aa\>"'/{print $1;exit}' file)
cc=$(expr "$aa" + 4)
dd=$(awk '$2=='"$cc"'{if (NR>="$cc")print $1;exit}' file)
echo "$aa $dd"

很笨。。。。。左边是最小值,后边是比最小值大三的数,且在最小值之后的数。

不知道如果最小值有几个要取哪一个?偶这里都取第一个匹配滴


 dbcat 回复于:2005-06-11 13:38:28

最小值:
awk '{print $2}' file | sort -n | head -1
位置:
awk '{print $2}' 2 | sort -n | head -1 |xargs -i expr
{} + 4 |xargs -i awk '{if($2~/{}/)print $1}' 2


 icesummit 回复于:2005-06-11 14:32:36

引用:原帖由 "dbcat" 发表:
最小值:
awk '{print $2}' file | sort -n | head -1
位置:
awk '{print $2}' 2 | sort -n | head -1 |xargs -i expr
{} + 4 |xargs -i awk '{if($2~/{}/)print $1}' 2



pfpf :!: 不过不能用~应该用==
if($2=={}/) :mrgreen:


 zleil 回复于:2005-06-11 20:25:36

BEGIN{ i=0; j=0; min=0; b3=0;}
{
if( i == 0 ){
    min = $2;
    i ++;
}else{
    if( $2 < min ){
        min = $2;
        j = 0;
    }else{
        if( j == 0 && $2 - min > 3){
            j = 1;
            b3 = $2;
        }
    }
}
}
END{ print "min=" min " b3=" b3; }

有语法错误吗?


 w123456 回复于:2005-06-13 10:01:42

awk '{print $2}' 2    


这里的2是什么意思?


 guangzongy 回复于:2005-06-13 10:26:03


awk '{if (NR==1) {min=$2;dat=$0;flag=1;} if ($2<min) {min=$2;dat=$0;flag=1;} if($2>(min+2)&&flag=
=1) {tag=NR;flag=0}}END{print "MIN item:"dat;print "TAG rowNo:"tag}' yourFile



 w123456 回复于:2005-06-13 10:40:49

新的要求:

求由最小值 恢复到80%平均值水平的时间差

数列的平均值为 7.76 
7.76 * 80%=6.2 

所以从最小值0 到 7  (第1次超过 6.2 )  的时间差为 20-15=5


 w123456 回复于:2005-06-13 10:44:28

dbcat   icesummit 
 不能排序的。

排序就对时间顺序大乱了,
“在最小值的后面数据,找出第一个  比最小值”  这一条件就无法实现了


 mocou 回复于:2005-06-13 10:47:04

偶的行不行,看到几位前辈的贴了了,偶都汗颜了


 guangzongy 回复于:2005-06-13 11:22:22

分了两步完成 :oops: 

#get min data and avg*80% data.
result=(`awk '{if(NR==1) min=$2; if(min>$2) min=$2;sum+=$2}END{print min" "sum/NR*0.8}' yourFile`)
#get the tag time.
awk '{if($2=='${result[0]}') {startPos=$1;flg="true";} if(flg=="true"&&$2>'${result[1]}') {print
$1-startPos;exit;}}' yourFile



 guangzongy 回复于:2005-06-13 11:27:43

引用:原帖由 "mocou"]偶的行不行,看到几位前辈的贴了了,偶都汗颜了
 发表:


条条大路通罗马 :mrgreen: 
BTW:[color=red]前辈[/color] :em06: ,估计几位大侠们会被叫得走不动道的 :em06:  :mrgreen:


 w123456 回复于:2005-06-13 16:22:52

多谢 guangzongy


 begincwcw 回复于:2005-06-13 16:26:13

试试这个:
cat filename:
1 10 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 1 
17 2 
18 4 
19 5 
20 7 
21 9 
22 10 
23 11 
24 10 
25 11 

程序如下:

nawk '{ line[NR] = $2 }
END{ for(i = 1; i <= NR; i++){
        avg += line 
        if(m == 0)
            min = line 
        else
            if(line < min){
                min = line
                x = i }
        m++ }
for(n = x; n <= NR; n++){
    if( line[n] - min > 3)
        break
    }
for(n1 = x; n1 <= NR; n1++){
    if( line[n1]  > avg / NR  *  0.8 )
        break
    }
{ printf("\n\n最小值为: %s\n第一个比最小值大于3 的数据位置是: %s行\n由最小值恢复到80%平均值水平的时间差为: %s秒 \n\n\n", min, n, n1 - x) }}'  filename

运行结果:

最小值为: 0
第一个比最小值大于3 的数据位置是: 18行
由最小值恢复到80%平均值水平的时间差为: 5秒


 w123456 回复于:2005-06-13 19:49:52

begincwcw  你的代码好C,呵呵


 begincwcw 回复于:2005-06-13 19:57:43

习惯了,w123456,我觉得你的问题很有针对性,我比较感兴趣。


 waker 回复于:2005-06-14 09:30:27

awk 'BEGIN{min=1000}

{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;sub(/\..*/,"",avg)
for (;!a[avg];avg++);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename


尝试扫描一次 :mrgreen:


 begincwcw 回复于:2005-06-14 13:14:46

waker,我觉得你的程序中,avg取整数的话有问题,如:平均数为6.28,第二十行为7的话没问题,但二十行为6的话,你的程序就有问题,就少一秒了。你可以试试?


 wayy2008 回复于:2005-06-14 13:22:07

找最小值,试一下这个:
sort -k2 filename|head -1
位置嘛,就比较麻烦一点了,呵呵。


 waker 回复于:2005-06-14 13:28:11

引用:原帖由 "begincwcw"]waker,我觉得你的程序中,avg取整数的话有问题,如:平均数为6.28,第二十行为7的话没问题,但二十行为6的话,你的程序就有问题,就少一秒了。你可以试试?
 发表:



那就改改,avg+1 是不是就行了? :mrgreen:


awk 'BEGIN{min=1000}
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;sub(/\..*/,"",avg)
for (;!a[++avg];);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename 



 begincwcw 回复于:2005-06-14 13:45:43

引用:原帖由 "waker"]那就改改,avg+1 是不是就行了?
 发表:



如果平均数是:5.82呢?


 waker 回复于:2005-06-14 14:18:39

5.82和5.02有什么区别?


 waker 回复于:2005-06-14 14:27:31

问题会出在avg正好是整数的时候,如果一行的值正好是平均值的80%时要不要计算在内,如果要

在 sub(....)前加一句 if(avg ~/\./)avg++好了


awk 'BEGIN{min=1000}
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;if(avg ~/\./)avg++;sub(/\..*/,"",avg)
for (;!a[avg];avg++);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename 



 begincwcw 回复于:2005-06-14 16:47:06

[quote:4509b98e93="awk 'BEGIN{min=1000} 
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}} 
END{ avg=sum/NR*0.8;if(avg ~/\./)avg++;sub(/\..*/,"",avg) 
for (;!a[avg];avg++); 
n=split(a[avg],b) 
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min 
print "offset: "b[j]-minline"s";exit}}}' filename 
"]


waker,我用你的程序测试了一下,测试结果如下:
cat filename
1 11 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 2 
17 3 
18 6 
19 8 
20 9 
21 11 
22 12 
23 13 
24 10 
25 11 

平均值:6.72
最小值为: 0
第一个比最小值大于3 的数据位置是: 18行
由最小值恢复到80%平均值水平的时间差为: 4秒 

就用你上面的程序运行,但你的程序什么也没有显示。

cat filename
1 11 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 1 
17 2 
18 4 
19 5 
20 7 
21 8 
22 10 
23 11 
24 10 
25 11 

平均值:6.208
最小值为: 0
第一个比最小值大于3 的数据位置是: 18行
由最小值恢复到80%平均值水平的时间差为: 5秒 

你的程序运行正确。
运行结果如下:
min: 0
offset: 5s

以上程序在unix5.0.5下测试,你可以去试试。


 waker 回复于:2005-06-14 21:02:48

awk 'BEGIN{min=1000}
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;[color=red]if(!avg ~/\./)avg++;[/color]sub(/\..*/,"",avg)
for (;!a[avg];avg++);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename 


逻辑错误  :mrgreen:  纠正一下,多谢指正


 waker 回复于:2005-06-15 08:30:37

是我的方法有问题,如果合适的值在min之前出现就会有问题


 waker 回复于:2005-06-15 09:09:21

改一下

awk 'BEGIN {min=10000}
{ sum+=$2; if ($2<min) {min=$2;minline=NR;delete a}a[$2]=NR}
END{  avg=sum/NR*0.8;
if(sub(/\..*/,"",avg)) avg++;
for (;!a[avg];avg++);
print "min: "min
print "offset: "a[avg]-minline"s"}' filename




 begincwcw 回复于:2005-06-15 11:23:11

waker可能我的awk版本与你的版本不一样,运行时提示delete a错误。


 waker 回复于:2005-06-15 12:33:36

`delete array ' 是gawk扩展
其它的版本可能是
for (i  in array) delete array的形式


 begincwcw 回复于:2005-06-15 14:03:47

引用:原帖由 "waker" 发表:
delete array ' 是gawk扩展 
其它的版本可能是 
for (i  in array) delete array的形式




多谢waker。




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=559921
转载请注明作者名及原文出处



收藏本页到: