我正在尝试将文件的内容与散列哈希进行比较。为此,我使用map
,if
和exists
,但效果不佳。
基本上,我想知道如果文件的第0列到第2列存在于哈希中。如果是这样,那么我想找出第3列是否作为内部哈希中的键存在。我的“旧文件.txt”是一个制表符分隔文件,我从中生成以下哈希:
old file.txt:
A s.av u
B s.bv u
C s.av u
C s.cv m
哈希:
my %oldhash = {
'A' => {'s.av' => ['u']},
'B' => {'s.bv' => ['u']},
'C' => {'s.av' => ['u'], 's.cv' => ['m']},
};
查看哈希中是否存在以下与“new file.txt”相关的制表符分隔列:
D Db Dc s.av #cols 0 - 2 do not exist in hash
E A Ab d.ef #column 1 exists, but column 3 doesn't, so nothing is done
E A Ac s.av #col 1 and 3 exist, so the new file will have the value of $oldhash{A}{s.av}
B Bb B s.bv #col0 and 3 exist, so I'll include the value of $oldhash{B}{s.bv}
请注意,cols 0和2都存在于散列中,但这并不重要,因为我只需要存在一个列。
输出可以与测试文件完全一样,添加的列从另一个文件中获取u
或m
。例如:
D Db Dc s.av #inserts empty column
E A Ab d.ef #inserts empty column
E A Ac s.av u #with u inserted
B Bb B s.bv u #with u inserted
这是我到目前为止的地方,但我得到的是exists argument is not a HASH or ARRAY element or a subroutine at myfile.pl line 24
:
#!/usr/local/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $dir='D:\\';
open my $oldfile, "<", "$dir\\old file.txt";
open my $newfile, "<", "$dir\\new file.txt";
my (%oldhash);
# creates the hash of hashes
while (my $odata = <$oldfile>){
chomp $odata;
my @oline = split /\t/, lc $odata;
push @{$oldhash{$oline[1]}{$oline[2]}}, $oline[3];
}
# does the comparison between the file and the hash
while (my $newlines = <$newfile>){
chomp $newlines;
my @line = split /\t/, $newlines;
if (exists map {$oldhash{$_}} @line[0..2]) {
print $oldhash{$_};
}
}
close $updatedtax;
close $oldtax;
我感谢你能给我的所有帮助!提前谢谢
答案 0 :(得分:3)
exists
需要一个数组或哈希元素作为其参数。您已经传递了一个标量值列表,这些标量值的来源在经过map
后就已丢失。
您可以将您的测试编写为
if ( grep { exists $oldhash{$_} }, @line[0..2] ) { ... }
但我认为有更好的方法来编写解决方案。
我认为这可以满足您的需求,但是根据您提供的数据,它只输出u
两次。您还没有按照我的要求显示所需的输出,这是正确的吗?
我已将您为自己%oldhash
选择的密钥反转,以便只需检查是否存在第四列(s.av
等)即可立即拒绝案例哈希。
我还添加了use autodie
作为必需来检查open
是否已经成功,然后再继续使用文件句柄,这避免了检查每个案例的明确性。
最后,我添加了chdir 'D:\\'
,这样您就不必在文件名前加上open
的路径。
输出包括最终的&#34;评论&#34;来自new_file.txt
的列引起了它。我相信你可以改变print
语句来提供你想要的输出。
use strict;
use warnings;
use autodie;
use Data::Dump;
chdir 'D:\\';
open my $old_fh, '<', 'old_file.txt';
my %old_data;
while (<$old_fh>) {
chomp;
my @fields = split /\t/;
$old_data{$fields[1]}{$fields[0]} = $fields[2];
print "@fields\n";
}
close $old_fh;
open my $new_fh, '<', 'new_file.txt';
while (<$new_fh>) {
chomp;
my @fields = split /\t/;
my $new = '';
if (my $list = $old_data{$fields[3]}) {
my @possible = grep defined, @{$list}{@fields[0,1,2]};
$new = $possible[0] if @possible;
}
print join("\t", @fields[0..3], $new, $fields[4]), "\n";
}
阅读文件后%old_data
的内容如下所示
(
"s.av" => { A => "u", C => "u" },
"s.bv" => { B => "u" },
"s.cv" => { C => "m" },
)
<强>输出强>
D Db Dc s.av #cols 0 - 2 do not exist in hash
E A Ab d.ef #column 1 exists, but column 3 doesn't, so nothing is done
E A Ac s.av u #col 1 and 3 exist, so the new file will have the value of $oldhash{A}{s.av}
B Bb B s.bv u #col0 and 3 exist, so I'll include the value of $oldhash{B}{s.bv}