1

我有一些文件,我正在尝试解析并从第三个文件构建哈希和查找。文件格式 :

文件 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 之间。

到目前为止我的想法:

  1. 取文件 2;将其解析为以 ID 为键的散列
  2. 取文件1;如果 ID 存在于文件 2 中;打开文件 3 并检查“a”的坐标范围并打印它

我执行了多远?不太远。我正在尝试读取文件 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;

但是,当然,我在这里做错了

4

2 回答 2

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" }],
}
于 2013-06-04T16:59:50.310 回答
1

我会这样处理你的任务:

  1. 将文件 1 加载到内存中并将其作为 ID 过滤器保存

  2. 绑定文件 3 或将其加载到内存中,否则将其保留以索引

  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>
于 2013-06-05T03:51:04.437 回答