我有文件,我正在尝试解析并从第三个文件构建哈希和查找。文件格式:
文件1:
ID2
ID4
文件2:
x1 y1 z1 ID1
x2 y2 z2 ID2
x3 y3 z3 ID2
x4 y4 z4 ID4
文件3:
a1 b1
a2 b2
a3 b3
我正在尝试做什么:
对于File1中的所有ID,使用File2中的ID字段查找x和y坐标,并查看File3中的“a”是否位于x和y之间。
到目前为止我的想法:
我执行了多远? 不太远。我试图读取文件2并解析散列中的所有元素,但我被卡住了:
while (<FILE>){
chomp $_;
my $line = $_;
my @arr = split ("\t", $line);
my $id = $arr[3];
if (exists ($hash{$id})) {
my $x = $arr[0];
my $y = $arr[1];
my $z = $arr[2];
push @{$hash{$id}{'x'}, $x;
push @{$hash{$id}{'y'}, $y;
push @{$hash{$id}{'y'}, $y;
} else {
$hash{'id'} = $id;
$hash{$id}{'x'} = $arr[0];
$hash{$id}{'y'} = $arr[1];
$hash{$id}{'z'} = $arr[2];
}
}
print Dumper %hash;
close FILE;
但当然,我在这里做错了什么
答案 0 :(得分:1)
这是将file2
读入哈希的方法。请注意,我认为使用三元素数组来保存x,y和z值而不是哈希值可能更容易。
我会展示更多,但我不清楚你的file3
如何运作,以及它与file1
的关系。您是否要处理file1
中的所有值,并为每个值查找file3
中哪些值介于相应限制之间?
use strict;
use warnings;
use autodie;
use Data::Dump;
open my $fh, '<', 'file2.txt';
my %data;
while (<$fh>){
chomp;
my @fields = split /\t/;
my $id = pop @fields;
for ('x' .. 'z') {
push @{$data{$id}{$_}}, shift @fields;
}
}
dd \%data;
<强>输出强>
{
ID1 => { x => ["x1"], y => ["y1"], z => ["z1"] },
ID2 => { x => ["x2", "x3"], y => ["y2", "y3"], z => ["z2", "z3"] },
ID4 => { x => ["x4"], y => ["y4"], z => ["z4"] },
}
<强>更新强>
虽然上述代码的存储格式是我认为你的意图,但我认为它不太可行。我认为如果你使用这个
,你可以更容易编写程序的其余部分while (<$fh>){
chomp;
my @fields = split /\t/;
my $id = pop @fields;
push @{$data{$id}}, \@fields;
}
导致此
{
ID1 => [["x1", "y1", "z1"]],
ID2 => [["x2", "y2", "z2"], ["x3", "y3", "z3"]],
ID4 => [["x4", "y4", "z4"]],
}
甚至是
while (<$fh>){
chomp;
my @fields = split /\t/;
my $id = pop @fields;
my %item;
@item{qw/ x y z /} = @fields;
push @{$data{$id}}, \%item;
}
导致此数据
{
ID1 => [{ x => "x1", y => "y1", z => "z1" }],
ID2 => [
{ x => "x2", y => "y2", z => "z2" },
{ x => "x3", y => "y3", z => "z3" },
],
ID4 => [{ x => "x4", y => "y4", z => "z4" }],
}
答案 1 :(得分:1)
我会以这种方式接近你的任务:
将文件1加载到内存中并将其保存为ID
绑定文件3或将其加载到内存中,否则将其保存到索引
将文件2作为请求流处理。
因此:
#! /usr/bin/env perl
use common::sense;
use Tie::File;
use autodie;
tie my @table, 'Tie::File', 'f3' or die $!;
my %filter;
open my $f, '<', 'f1';
while (<$f>) {
chomp;
$filter{$_}++
}
close $f;
while (<>) {
next unless /^x(\d+) y(\d+) z\d+ (ID\d+)$/;
next unless exists $filter{$3};
say((split ' ', $table[$2])[$1])
}
untie @table;
用法:
$ ./example
x1 y1 z2 ID2
b2
x0 y0 z5 ID2
a1
$ ./example file2
<three blank lines, because your examples are 1-indexed>