对数组进行排序以获得唯一记录

时间:2014-05-11 18:45:14

标签: perl

我有一个制表符分隔的文件:

AA      11
AA      22
AA      11
AA      22
BBB     44
BBB     77
BBB     44
BBB     77

我想打印文件的不同行:

AA      11
AA      22
BBB     44
BBB     77

我写了这个Perl脚本来做到这一点:

#!/usr/bin/perl
$file1=$ARGV[0];
%record;
open(FP1,"$file1");
while($s1=<FP1>)
{
    chomp($s1);
    @array= split(/\t/,$s1);
    $name1=$array[0];
    $name2=$array[1];
    push @{$record{$name1}{trs}}, $name2;
    $ref=\%record;
}
for $name1 ( sort { $a <=> $b } keys %record )
{
    my $name2   = $$ref{$name1}{trs};
    print "$name1\t$name2\n";
}

但它不起作用。有人可以帮忙吗?

3 个答案:

答案 0 :(得分:3)

如果您不想更改订单行,则不必先将整个文件读入内存,

use strict;
use warnings;
use autodie;

my $file1 = $ARGV[0];
my %seen;
open(my $FP1, "<", $file1);

while (my $s1 = <$FP1>) {
  next if $seen{$s1}++;
  print $s1;
}

答案 1 :(得分:1)

主要问题是您将AA记录存储在名为@{$record{'AA'}{trs}}的数组中(即@{$record{'AA'}->{'trs'}}),但是当您打印这些记录时,您不会迭代该数组,你只是尝试将其作为标量读取。

您的文件以制表符分隔的这一事实似乎并不相关,因为如果两条记录不同,您显然会认为两条线是不同的。因此,您不必担心将线路转换为&#34;记录&#34;用于处理。

(即使除此之外,你还有很多不必要的代码 - 例如,根本没有理由创建$ref。)

您实际上可以省去Perl,并使用标准sort实用程序:

sort -u <INPUT_FILE >OUTPUT_FILE

答案 2 :(得分:1)

如果行与完全匹配,则您需要的只是来自List::MoreUtilsuniq函数

use strict;
use warnings;

use List::MoreUtils 'uniq';

my @data = <DATA>;
chomp @data;
print "$_\n" for uniq @data;


__DATA__
AA  11
AA  22
AA  11
AA  22
BBB 44
BBB 77
BBB 44
BBB 77

<强>输出

AA  11
AA  22
BBB 44
BBB 77

如果您无法安装List::MoreUtils并且不能安装uniq,那么您必须编写类似这样的内容

use strict;
use warnings;

use List::MoreUtils 'uniq';

my @data = <DATA>;
chomp @data;

my (@unique, %unique);
for (@data) {
    push @unique, $_ unless $unique{$_}++;
}

print "$_\n" for @unique;

输出与前一个示例相同。