【问题标题】:Perl compare array values with values in a hash of arraysPerl 将数组值与数组哈希中的值进行比较
【发布时间】:2013-03-27 22:51:38
【问题描述】:
该帖子已根据 cmets 和 DVK 的回答进行了更新

我已更改为使用 3 参数形式的 open 并将 ID 正确推送到数组中

以下更新代码

use warnings;
use strict;
use Data::Dumper;


my $file1 = "Inputfile.txt";
my $file2 = $ARGV[0];
my $file3 = $ARGV[1];

open (OF, " > Results.txt") or die "Can't write new file: $!";

my %hash;
open(INPUT1, "<" , $file1)or die("Failed to open file1: $!");
while (!eof(INPUT1)) {
    my @elements = split(/\t/, <INPUT1>);
    my $F1catagory = $elements[2];
    my $F1IDs = $elements[3];
    push @{$hash{$F1catagory}}, $F1IDs;
}
close(INPUT1);

my @array1;
open(INPUT2, "<" , $file2) or die ("Failed to open file2: $!");
while (!eof(INPUT2)) {
    my @line = split(/\t/, <INPUT2>);
    my $F2catagory = $line [0];
    my $F2IDs    = $line [1];
    push (@array1, $F2IDs);
}
print OF @array1;
close(INPUT2);

my @array2;
open(INPUT3, "<" , $file3) or die ("Failed to open file3: $!");
while (!eof(INPUT3)) {
    my @lines = split(/\t/, <INPUT3>);
    my $F3catagory     = $lines [0];
    my $F3IDs = $lines [1];
    push (@array2, $F3IDs );


}
print OF @array2;
close(INPUT3);

输入数据看起来像

以下

文件 1 包含有关进程的信息,如下所示,第 3 列包含进程 ID,第 4 列包含项目 ID(这些用于创建我的 %hash)

process 9606    0051712 3458    [25 Jul 2011]
process 9606    0051712 2208    [25 Jul 2011]
process 9606    0051712 2150    [25 Jul 2011]
process 9606    0051712 4843    [25 Jul 2011]
process 9606    0032513 2280    [25 Jul 2011]
process 9606    0032513 2281    [25 Jul 2011]
process 9606    0006285 23583   [25 Jul 2011]
process 9606    0006285 6996    [25 Jul 2011]
process 9606    0006285 4913    [25 Jul 2011]
process 9606    0006285 10309   [25 Jul 2011]
process 9606    0006285 4350    [25 Jul 2011]
process 9606    0006285 4968    [25 Jul 2011]
process 9606    0006285 4595    [25 Jul 2011]
process 9606    0006285 8930    [25 Jul 2011]
process 9606    0051503 284439  [25 Jul 2011]
process 9606    0051503 2697    [25 Jul 2011]
process 9606    0051503 291 [25 Jul 2011]
process 9606    0051503 10478   [25 Jul 2011]

file2 包含 column1 中项目的类别和第 2 列中的项目 ID

CS1G2   1455
TM65    157378
PFN1    5216
HUL1    11100
ERI3    79033
PR12    57479
HIFN    55662
HNPD    3184
 HI2    28996
 LD1    84316
GRB2    2885
 AL6    84964
PCM1    5108
 ZN7    126208
MAK2    5605
BCL3    602

文件 3 与文件 2 相同,只是项目 ID 不同

我需要确定文件 1 中的任何进程是否包含文件 2 和文件 3 中的项目。

我希望这能让问题更清楚

#######原创问题

我一直在尝试编写的脚本遇到问题

我有一个包含进程信息的文件,我已将进程 ID 和项目 ID 读入数组哈希,其中进程 ID 作为键,项目 ID 作为值(数组哈希作为单个进程中的多个项目)

我有两个项目 ID 数组 @F2IDs 和 @F3IDs

如果在同一进程中的@F2IDs 和@F3IDs 中有任何项目ID(在相同的%hash 值中)我想确定它在同一个进程中

到目前为止我有这个代码

use warnings;
use strict;
use Data::Dumper;

my $file1 = "Infile.txt";
my $file2 = $ARGV[0];
my $file3 = $ARGV[1];

open (OF, " > Results.txt") or die "Can't write new file: $!";


my %hash;
open(INPUT, $file1)or die("Failed to open file2");
while (!eof(INPUT)) {
    my @elements = split(/\t/, <INPUT>);
    my $F1catagory = $elements[2];
    my $F1IDs = $elements[3];
    push @{$hash{$catagory}}, $F1IDs;
}
close(INPUT);

open(INPUT, $file2) or die "Can't write new file: $!";
while (!eof(INPUT)) {
    my @line = split(/\t/, <INPUT>);
    my $F2catagory = $line [0];
    my @F2IDs    = $line [1];
}
close(INPUT);

open(INPUT, $file3) or die "Can't write new file: $!";
while (!eof(INPUT)) {
    my @lines = split(/\t/, <INPUT>);
    my @F3catagory     = $lines [0];
    my @F3IDs = $lines [1];
}
close(INPUT);    

我需要做一些类似下面的伪代码,但不知道 perl 中是否有像 python 中那样的“if in”构造

$insameprocess = False;
foreach value in %hash;
    if F2IDs and F3IDs are in {$hash{$catagory}};;
       $insameprocess = True;
       print OF "the key the value and if they are in the same process";

有没有人知道如何在 perl 中做到这一点?

提前感谢您的帮助 问候

S

【问题讨论】:

  • 作为一个无关的旁注,您使用open 的方式是不安全的,并且可能由于使用全局文件句柄而导致错误。请使用带有词法文件句柄的 3 参数形式:open(my $input, "&lt;" , $file1 ) or die("Failed to open $file1: $!");
  • 能否请您举例说明您的输入数据和输出数据的内容以及预期结果?这个词的描述有点混乱。
  • 我已经编辑了 m 个问题来解释这些 cmets。你能帮我进一步吗?我认为这个问题现在更清楚了。非常感谢您到目前为止的帮助。我无法理解 perl。

标签: arrays perl hash


【解决方案1】:

你有 3 个问题:

  1. 一般来说,您的脚本在读取数据时似乎包含很多错误。我暂时不会讨论这个,因为这不是你问的。例如,您需要在循环 2/3 中将 ID 推送到数组中,而不是分配给数组(您在第一个循环中正确执行了此操作)。

  2. 您的主要技术问题似乎是“如何判断哈希值中是否有某个 ID(这是一个数组 ref)?”。

    解决此问题的最佳方法是将数据存储在 ID 的 hashref(映射到“1”)而不是 ID 的 arrayref 中,并使用哈希查找:

    # This is in your first loop reading file 1
    # OLD CODE:    push @{$hash{$catagory}}, $F1IDs;
    # NEW CODE:
    # # Each hash value is a hashref, with keys being IDsx and values simply 1
    $hash{$catagory}->{$F1IDs} = 1; 
    
    # This is the code in the end, to check if some ID is in the hash:
    if ($hash{$catagory}->{$F1IDs}) {
        # $id_is_in_hash = 1;
    }
    
  3. 坦率地说,您的伪代码对我(也包括您的描述)没有太大意义,因此我无法帮助您编写一份完整的检查,使用我在第 2 点中的解决方案替换您的伪代码。如果您可以提供更明确的描述,或者在 3 个文件中提供更好的示例数据和所需的输出,我将能够做得更多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-06
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    相关资源
    最近更新 更多