【问题标题】:counting how many time the order of two consecutive number in a file are reversed in a second file in BASH计算文件中两个连续数字的顺序在 BASH 中的第二个文件中颠倒了多少次
【发布时间】:2013-01-12 16:34:15
【问题描述】:

我遇到了以下问题:

给定 2 个包含 N 个数字的文件

file1.dat: 1,2,3,4,5,6,7,8,9,0

file2.dat: 2,5,4,7,6,9,8,1,0,3

file2.dat 实际上只是第一个的改组版本。 我想知道第一个文件中两个连续数字的顺序在第二个文件中改变了多少次(包含相同的数字)。例如,在文件一中我们开始寻找1和2,在第二个文件中,2在1之前,所以顺序发生了变化;在第一个文件中有 9,然后是 0,在第二个文件中,这个顺序保持不变,因为 9 在 0 之前。

我使用的实际数据大致由 26000 个数字组成,它们都是不同的。

我想到了类似的东西:

for(i=0; i<N-1; i++)
    for(j=0; j<N; j++)
      for(k=0 ; k<N; k++)
        if(B[j]==A[i] && B[k]==A[i+1] && k < j )
        count++

     print("The number of inversion is: %d\n",count)

但我不知道如何在 awk 中编写它(我写了一个小 C 程序,但需要 5 个多小时才能给我答案)而且我不知道类似的东西是否可以给我一个结果合理的时间。

【问题讨论】:

  • 为什么你要解决这个是Bash还是AWK?您是否以某种方式假设脚本语言中的相同解决方案会比 C 中运行得更快?
  • 这就是我所希望的,也因为它们是我所知道的仅有的两种语言。如果 C 失败,我希望 BASH 或 AWK 能做得更快。
  • 你只关心那些邻居对吗?例如在file2 4..1中的file1 1..4中,这是否也应该计算在内?顺便说一句,你能给出你的 file1,file2(10 个数字)例子的正确答案/结果吗?
  • 如果您的 C 程序需要 5 个小时才能运行,那么问题在于您的算法而不是您正在编程的工具,并且在 bash 或 awk 中该算法的任何实现都将比在 C 中运行得慢所以这可能不是最好的建议论坛——你需要的是算法,而不是工具。
  • 你现实世界中file1中的数字是否也遵循规则..i-1, i, i+1..?还是..i-n, i, i+n...?

标签: algorithm bash awk


【解决方案1】:

我希望你的两个文件遵守一定的规则:

  • 相同数量的不同数字,
  • 两个文件都有一行

我没有做那些格式检查。查看我的解决方案:

awk -F, 'FNR==NR{n=NF;for(i=1;i<=NF;i++)o[i]=$i;next;}
        {for(i=1;i<=NF;i++)v[$i]=i}
        END{ for(i=1;i<=n-1;i++) t+=v[o[i]]>v[o[i+1]]?1:0;
                print "inversions:",t;
        }' file1 file2

测试:

kent$  head file1 file2
==> file1 <==
1,2,3,4,5,6,7,8,9,0

==> file2 <==
2,5,4,7,6,9,8,1,0,3


kent$  awk -F, 'FNR==NR{n=NF;for(i=1;i<=NF;i++)o[i]=$i;next;}
        {for(i=1;i<=NF;i++)v[$i]=i}
        END{ for(i=1;i<=n-1;i++) t+=v[o[i]]>v[o[i+1]]?1:0;
                print "inversions:",t;
        }' file1 file2
inversions: 5

如果你想打印一些调试信息,比如打印反转对,请看这个:

kent$  awk -F, 'FNR==NR{n=NF;for(i=1;i<=NF;i++)o[i]=$i;next;}
        {for(i=1;i<=NF;i++)v[$i]=i}
        END{ for(i=1;i<=n-1;i++) {

        if(v[o[i]]>v[o[i+1]]){
                print "inversion pair foud:"o[i],o[i+1]
                t++;
        }
        }
                print "inversions:",t;
        }' file1 file2

inversion pair foud:1 2
inversion pair foud:3 4
inversion pair foud:4 5
inversion pair foud:6 7
inversion pair foud:8 9
inversions: 5

如果您想要一些其他信息,例如原始索引/顺序,更改顺序,也很容易添加。

希望对你有帮助。

编辑

如果您的数据文件是单列格式。试试这个:

 awk -F, 'FNR==NR{o[NR]=$0;next;}{v[$0]=FNR;n=FNR}
        END{ for(i=1;i<=n-1;i++) t+=v[o[i]]>v[o[i+1]]?1:0;
                print "invertions:",t;
        }' file1 file2

测试截屏。只是为了测试我刚刚写的录音脚本;)

【讨论】:

  • 哎呀,应该找到了...错字对不起...如果需要编辑答案,我会修复它...
  • 我正在尝试运行脚本,但它不起作用。也许是因为我的原始文件是一个列文件?
  • @ValerioD.Ciotti 你可以在 vim 中打开它并输入 :%s/\n/,/g 哦,也许你必须删除尾逗号。无论如何,更改我的 awk 脚本以适应您的格式单行 -> 单列也很容易。我应该这样做吗?
  • @ValerioD.Ciotti 我认为一个新问题更好.. 它发生在 1 个月前,我忘记了发生了什么,我必须阅读所有问题、答案和 cmets....
  • 好的,我会提出一个新问题
【解决方案2】:

我知道你已经有了一个公认的干净答案。

只是分享:

sgeorge-mn:~ sgeorge$ cat stack.sh 
VALUE1=$1
VALUE2=$2
for POS in `sed 's/,/ /g' file1.dat`
do
((COUNT++))
if [[ $VALUE1 == $POS ]] ; then
    VAL1_POS=$COUNT
fi

if [[ $VALUE2 == $POS ]] ; then
        VAL2_POS=$COUNT
fi
done


for MATCH in `sed 's/,/ /g' file2.dat`
do
((COUNT2++))
if [[ $VALUE1 == $MATCH ]] ; then
        VAL1_POS2=$COUNT2
fi
if [[ $VALUE2 == $MATCH ]] ; then
        VAL2_POS2=$COUNT2
fi
done

if [[ $VAL1_POS -gt $VAL2_POS ]] ; then
    P1=1
fi
if [[ $VAL1_POS2 -gt $VAL2_POS2 ]] ; then
    P2=1
fi

if [[ $VAL1_POS -lt $VAL2_POS ]] ; then
    P1=2
fi
if [[ $VAL1_POS2 -lt $VAL2_POS2 ]] ; then
    P2=2
fi

if [[ $VAL1_POS -eq $VAL2_POS ]] ; then
    P1=3
fi
if [[ $VAL1_POS2 -eq $VAL2_POS2 ]] ; then
    P2=3
fi

if [[ $P1 == $P2 ]]; then
    echo "No order change"
else
    echo "Order changed"
fi

如何执行脚本:

我假设如下:

  • 两个文件的编号完全相同,顺序相同。
  • 您不会将不存在的号码(file*.dat 中不存在)作为脚本的输入
sgeorge-mn:~ sgeorge$ bash stack.sh 5 7
No order change
sgeorge-mn:~ sgeorge$ bash stack.sh 4 5
Order changed
sgeorge-mn:~ sgeorge$ bash stack.sh 9 0
No order change
sgeorge-mn:~ sgeorge$ bash stack.sh 1 2
Order changed

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 2016-11-20
    相关资源
    最近更新 更多