我有一个制表符分隔的文本文件(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
答案 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