用数字比较两个文本

时间:2013-12-09 01:40:28

标签: arrays perl comparison numerical

我有这两个文件,我想用数字比较它的内容。

文本1:

C_A C_A 0.0000 0.0000 0 0 50 47 100 390
C_A/I0/I0 INV 0.0200 0.2210 0 0 20 200 30 100
C_A/I0/I2 INV 1.0400 0.2210 0 0 530 200 250 261

文本2:

C_A C_A 0.0000 0 0 0 50 47 100 390
C_A/I0/I0 INV 0.0200 0.2213 0 0 20 200 30 100
C_A/I0/I2 INV 1.04 0.2210 0 0 530 200.00 250 261

期望的输出:

C_A/I0/I0 INV has mismatch property.

到目前为止我已经尝试了这个但是我遇到了use of uninitialized value的错误。请告诉我。感谢您的帮助。

编辑代码:

use strict;
use warnings;
my %ref_data;

open my $fh, '<', 'Text1' or die $!;
while (<$fh>) {
    chomp;
    my ($occurname, $tempname, @data) = split;
    $ref_data{$occurname} = \@data;
    }

open $fh, '<', 'Text2' or die $!;
while (<$fh>) {
    chomp;
    my ($occurname, $tempname, @data1) = split;
    my $data = $ref_data{$occurname};
    print "$occurname $tempname has mismatch property\n" if 
        grep { $data1[$_] != $data->[$_] } 0 .. $#data1;
      }
    } 

4 个答案:

答案 0 :(得分:2)

也许以下内容会有所帮助:

use strict;
use warnings;

my $file2 = pop;
my %ref_data;

while (<>) {
    my ( $occurname, $tempname, @data1 ) = split;
    $ref_data{$occurname} = \@data1;
}

push @ARGV, $file2;

while (<>) {
    my ( $occurname, $tempname, @data2 ) = split;
    my $data1 = $ref_data{$occurname};

    for ( 0 .. $#data2 ) {
        if ( $data1->[$_] != $data2[$_] ) {
            print "$occurname $tempname has mismatch property\n";
            last;
        }
    }
}

用法:>perl script.pl Text1 Text2 [>outFile]

最后一个可选参数将输出定向到文件。

数据集的输出:

C_A/I0/I0 INV has mismatch property

这让Perl处理文件i / o。此外,for循环用于比较数组内容 - 而不是grep - 因为如果找到不匹配,它可以快速终止。

答案 1 :(得分:1)

您可以以整数模式打包它们,然后比较打包值..

  unpack('s', $val1) != unpack('s', $val2);

来自perldoc的注意事项:但不要指望奇迹:如果打包值超过分配的字节容量,则高位位被静默丢弃,并且解压缩肯定无法将它们从某些神奇的帽子中拉回来。并且,当您使用签名的模板代码(如s)进行打包时,超出的值可能会导致符号位设置,并且解压缩它将巧妙地返回负值。

答案 2 :(得分:1)

smartmatch operator怎么样?

while (<$fh>) {
    my ($occurname, $tempname, @data1) = split;
    my $data = $ref_data{$occurname};
    print "$occurname $tempname has mismatch property\n" unless @$data ~~ @data1;
}

如果您的Perl不够新(<5.10.1),请使用TLP的想法。

编辑:添加了匹配数组长度的检查,以便在数组大小不同时扼杀未初始化的值警告。

if (@data1 != @$data || grep { $data1[$_] != $data->[$_] } 0 .. $#data1) {
    print "$occurname $tempname has mismatch property\n";
}

请参阅grep

另外section on arrays here for $#array

答案 3 :(得分:1)

根据您需要的精确程度,我只需减去两者并测试它是否非常接近于零:

if ( grep { my $delt= $data[$_] - $data1[$_] ;  return ( $delt < -1e-16 ) || ( $delt > 1e-16 ) ; } 1..$#data

注意我将范围从0..$data更改为1..$#data。您不需要比较文本的第一个字段。