【问题标题】:Find key in subhash without iterate through the whole hash在不遍历整个哈希的情况下查找子哈希中的密钥
【发布时间】:2020-03-29 12:57:41
【问题描述】:

我有一个看起来像这样的哈希:

my $hash = {
    level1_f1 => {
                  level2_f1 => 'something',
                  level2_f2 => 'another thing'
    },
    level1_f2 => {
                  level2_f3 => 'yet another thing',
                  level2_f4 => 'bla bla'
                  level2_f5 => ''
    }
...
 }

我还得到了一个与“level2”键对应的值列表,我想知道它是否存在于哈希中。

@list = ("level2_f2", "level2_f4", "level2_f99")

我不知道@list 的每个元素属于哪个“level1”键。我认为找到它们是否存在的唯一方法是使用 foreach 循环遍历@list,另一个 foreach 循环遍历 %hash 的键并检查

foreach my $i (@array) {
  foreach my $k (keys %hash) {
     if (exists $hash{$k}{$list[$i]})
 }
}

但我想知道是否有更有效或更优雅的方式来做到这一点。我找到的所有答案都要求您知道“level1”键,而我不知道。

谢谢!!

【问题讨论】:

    标签: perl hash


    【解决方案1】:

    使用values:

    for my $inner_hash (values %$hash) {
        say grep exists $inner_hash->{$_}, @list;
    }
    

    【讨论】:

      【解决方案2】:

      您必须循环所有 level1 键。但是,如果您不需要知道哪些键匹配并且只关心任何键的存在,那么您不必明确询问列表中的每个成员。你可以说

      foreach my $k (keys %hash) {
         if ( @{ $hash{$k} }{ @list } )
         {
         }
      }
      

      哈希切片将返回子哈希中所有在列表中具有匹配键的值。列表中不在子哈希中的键将被忽略。

      但是请注意,这可能会比您实际需要的更多。

      【讨论】:

        【解决方案3】:

        您不需要遍历“整个哈希”。

        您必须遍历外部哈希的元素,因为您想检查每个元素的值,但您不需要遍历内部哈希的元素。您的解决方案已经证明了这一点。

        因此,您的解决方案尽可能高效,至少就其可扩展性而言。您只能执行小的优化,例如在找到匹配项后立即停止。

        for my $i (@list) {
           while ( my (undef, $inner) = each(%hash) ) {
              if (exists($inner->{$i}) {
                 ...
                 last;
              }
           }
        
           keys(%hash);   # Reset iterator since it might not be exhausted.
        }
        

        作为一种微优化,反转循环的嵌套可能是有益的。

        my %list = map { $_ => 1 } @list;
        
        while ( my (undef, $inner) = each(%hash) ) {
           while (defined( my $k = each(%$inner) )) {
              if ($list{$k}) {
                 delete($list{$k});
                 ...
                 last if !keys(%list);
              }
        
           }
        
           keys(%$inner);   # Reset iterator since it might not be exhausted.
           last if !keys(%list);
        }
        
        keys(%hash);   # Reset iterator since it might not be exhausted.
        

        如果哈希值很小,这些更改实际上可能会减慢速度。

        老实说,如果确实存在速度问题,那么问题在于您为要运行的查询类型使用了错误的数据结构!

        【讨论】:

        • 您认为什么是更好的数据结构?我倾向于总是考虑哈希
        • 什么数据结构可以让你快速检查它是否包含字符串?一个由您要搜索的字符串键入的哈希值。 (与您所拥有的相反:一个哈希值是由您要搜索的字符串键入的哈希值。)
        猜你喜欢
        • 2019-09-08
        • 2012-08-22
        • 2014-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-01
        • 1970-01-01
        相关资源
        最近更新 更多