在哈希中匹配值

时间:2013-04-15 17:40:33

标签: regex perl hashtable match

我有两个哈希数组。我想根据第一个变量缩小第二个范围。

第一个数组包含带有键seqnamesourcefeaturestartendscore,{{1}的哈希值},strandframegeneID

第二个数组包含带键的哈希值 transcriptIDorganismgeneIDnumbermotifnumberpositionstrand

我想要做的是,从第一个哈希数组中删除所有哈希,其中包含变量sequence,其中 第二个数组的哈希值。 - 注意两种类型的哈希都有geneID密钥。简单地说,我想在第一个数组中保留这些哈希值,这些哈希值具有geneID值,这些值可以在第二个数组的哈希值中找到。

到目前为止,我的尝试是两个循环:

geneID

但是我不确定这是解决这个问题的正确方法。

2 个答案:

答案 0 :(得分:2)

对于初学者,$a =~ /$b/不检查是否相等。你需要

$second_hash_array[$j]{geneID} =~ m/^\Q$first_hash_array[$i]{geneID}\E\z/

或只是

$second_hash_array[$j]{geneID} eq $first_hash_array[$i]{geneID}

为此。


其次,

for my $i (0 .. $#first_hash_array) {
   ... $first_hash_array[$i] ...
}

可以更简洁地写成

for my $first (@first_hash_array) {
   ... $first ...
}

列表中的下一个是

for my $second (@second_hash_array) {
    if (...) {
       push @subset, $second;
    }
}

可以多次将$second添加到@subset。您需要添加last

# Perform the push if the condition is true for any element.
for my $second (@second_hash_array) {
   if (...) {
      push @subset, $second;
      last;
   }
}

或将push移出循环

# Perform the push if the condition is true for all elements.
my $flag = 1;
for my $second (@second_hash_array) {
   if (!...) {
      $flag = 0;
      last;
   }
}

if ($flag) {
   push @subset, $second;
}

取决于你想做什么。


要从数组中删除,可以使用splice。但是从数组中删除会弄乱所有索引,因此最好向后迭代数组(从最后一个索引到第一个索引)。

它不仅复杂,而且价格昂贵。每次拼接时,阵列中的所有后续元素都需要移动。

更好的方法是过滤元素并将结果元素分配给数组。

my @new_first_hash_array;
for my $first (@first_hash_array) {
   my $found = 0;
   for my $second (@second_hash_array) {
      if ($first->{geneID} eq $second->{geneID}) {
         $found = 1;
         last;
      }
   }

   if ($found) {
      push @new_first_hash_array, $first;
   }
}

@first_hash_array = @new_first_hash_array;

反复迭代@second_hash_array是不必要的代价。

my %geneIDs_to_keep;
for (@second_hash_array) {
   ++$geneIDs_to_keep{ $_->{geneID} };
}

my @new_first_hash_array;
for (@first_hash_array) {
   if ($geneIDs_to_keep{ $_->{geneID} }) {
      push @new_first_hash_array, $_;
   }
}

@first_hash_array = @new_first_hash_array;

最后,我们可以将for替换为grep,以提供以下简单有效的答案:

my %geneIDs_to_keep;
++$geneIDs_to_keep{ $_->{geneID} } for @second_hash_array;

@first_hash_array = grep $geneIDs_to_keep{ $_->{geneID} }, @first_hash_array;

答案 1 :(得分:1)

我就是这样做的。

为所需的geneID创建一个数组 req_geneID ,并将第二个哈希的所有geneIds放入其中。

遍历第一个哈希并检查 genq_ 是否包含在 req_geneID 数组中。(它很容易使用& #34;包含?"但您可以在perl中尝试this

最后使用perl中的this删除与 req_geneID 中的任何geneID不匹配的哈希

for (keys %hash)
{
    delete $hash{$_};
}

希望这会有所帮助.. :)