Perl在第一列中找到重复项并转换为唯一的自动递增值

时间:2015-06-04 13:35:04

标签: perl

我有一个制表符分隔的文本文件(test.txt),如下所示:

Steve   ran 100 200 300
Steve   sit 50  30  20
Steve   steal   40  60  70
Bill    ran 10  20  90
Bill    get 14  15  30
John    up  34  38  29
John    ran 10  40  60
John    down    60  70  80
John    yep 40  69  80

我需要用唯一标识符替换第1列中的重复值,即Steve => Name_1,Bill => Name_2,John => Name_3等文本文件的顺序很重要,所以逐行读取?这就是我到目前为止所拥有的......

use strict;
use warnings;
use autodie;

open my $fh, "<", 'test.txt';
while (<$fh>) {
    my @row = split(/\s+/,$_);
    print "$row[0]\t$row[1]\t$row[2]\t$row[3]\t$row[4]\n";  
    }

close $fh;
exit;

我想要的输出是:

Name_1   ran 100 200 300
Name_1   sit 50  30  20
Name_1   steal   40  60  70
Name_2   ran 10  20  90
Name_2   get 14  15  30
Name_3   up  34  38  29
Name_3   ran 10  40  60
Name_3   down    60  70  80
Name_3   yep 40  69  80

2 个答案:

答案 0 :(得分:0)

每当需要删除重复项时,使用哈希通常是一种很好的方法。

在这种情况下,您需要在while循环之外声明散列,然后检查每个名称以查看它是否已存在于散列中。如果是,请使用has中的值,否则创建一个新键,并存储所需的值。

类似的东西:

use strict;
use warnings;
use autodie;

open my $fh, "<", 'test.txt';
my %names;
my $count;
while (<$fh>) {
    my @row = split(/\s+/,$_);
    if (not exists $names{$row[0]}) {
        $names{$row[0]} = "Name_" . ++$count;
    }
    print "$names{$row[0]}\t$row[1]\t$row[2]\t$row[3]\t$row[4]\n";  
}

close $fh;
exit;

答案 1 :(得分:0)

这会按照你的要求行事。它保留一个哈希%names,记录每个原始值的替换名称。数字$n会跟踪要分配给新发生名称的下一个数字

use strict;
use warnings;
use 5.010;
use autodie;

my %names;
my $n;

open my $fh, '<', 'test.txt';
while ( <$fh> ) {
  chomp;
  my @fields = split /\t/;
  $fields[0] = $names{$fields[0]} //= 'Name_'.++$n;
  say join "\t", @fields;
}

<强>输出

Name_1  ran 100 200 300
Name_1  sit 50  30  20
Name_1  steal 40  60  70
Name_2  ran 10  20  90
Name_2  get 14  15  30
Name_3  up  34  38  29
Name_3  ran 10  40  60
Name_3  down  60  70  80
Name_3  yep 40  69  80