如何检查密码是否存在于深层Perl哈希中?

前端之家收集整理的这篇文章主要介绍了如何检查密码是否存在于深层Perl哈希中?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如果我在 understand correctly调用if(存在$ ref-> {A} – > {B} – > {$ key}){…}将弹出$ ref-> {A}和$ ref – > {A} – > {B}即使它们在if之前不存在!

这似乎是非常不需要的。那么我该怎么检查一个“深”哈希键是否存在?

解决方法

使用像 autovivification模块这样的东西来关闭这个功能,或者使用 Data::Diver.好了,但这是我期望程序员自己知道如何做的简单任务之一。即使你不在这里使用这种技术,你应该知道它的其他问题。这实际上是Data :: Diver在剥离界面时正在做的事情。

一旦遇到了数据结构的窍门(如果您不想使用一个可以为您完成的模块),这很容易。在我的例子中,我创建一个check_hash子例程,它使用一个哈希引用和一个键的数组引用进行检查。它一次检查一个级别。如果钥匙不在那里,它什么也不返回。如果钥匙在那里,它将哈希修剪到路径的那一部分,然后用下一个键再次尝试。诀窍是$ hash始终是要检查的树的下一部分。我将存在于eval中,以防下一级别不是哈希引用。如果路径末尾的哈希值是某种假值,那么技巧就不会失败。这是任务的重要部分:

sub check_hash {
   my( $hash,$keys ) = @_;

   return unless @$keys;

   foreach my $key ( @$keys ) {
       return unless eval { exists $hash->{$key} };
       $hash = $hash->{$key};
       }

   return 1;
   }

不要害怕所有的代码在下一个位。重要的部分只是check_hash子程序。一切都是测试和示范:

#!perl
use strict;
use warnings;
use 5.010;

sub check_hash {
   my( $hash,$keys ) = @_;

   return unless @$keys;

   foreach my $key ( @$keys ) {
       return unless eval { exists $hash->{$key} };
       $hash = $hash->{$key};
       }

   return 1;
   }

my %hash = (
   a => {
       b => {
           c => {
               d => {
                   e => {
                       f => 'foo!',},f => 'foo!',g => 'goo!',h => 0,f => [ qw( foo goo moo ) ],g => undef,f => sub { 'foo!' },);

my @paths = (
   [ qw( a b c d     ) ],# true
   [ qw( a b c d e f ) ],# true
   [ qw( b c d )       ],# false
   [ qw( f b c )       ],# false
   [ qw( a f )         ],# true
   [ qw( a f g )       ],# false
   [ qw( a g )         ],# true
   [ qw( a b h )       ],# false
   [ qw( a )           ],# true
   [ qw( )             ],# false
   );

say Dumper( \%hash ); use Data::Dumper; # just to remember the structure    
foreach my $path ( @paths ) {
   printf "%-12s --> %s\n",join( ".",@$path ),check_hash( \%hash,$path ) ? 'true' : 'false';
   }

这是输出(减去数据转储):

a.b.c.d      --> true
a.b.c.d.e.f  --> true
b.c.d        --> false
f.b.c        --> false
a.f          --> true
a.f.g        --> false
a.g          --> true
a.b.h        --> true
a            --> true
             --> false

现在,你可能想要一些其他的检查而不是存在。也许你想检查所选路径上的值是否为真,还是一个字符串,或另一个哈希引用,或其他。这只是在验证路径存在后提供正确的检查。在这个例子中,我传递一个子程序引用,它将检查我离开的值。我可以检查我喜欢的任何东西:

#!perl
use strict;
use warnings;
use 5.010;

sub check_hash {
    my( $hash,$sub,$keys ) = @_;

    return unless @$keys;

    foreach my $key ( @$keys ) {
        return unless eval { exists $hash->{$key} };
        $hash = $hash->{$key};
        }

    return $sub->( $hash );
    }

my %hash = (
    a => {
        b => {
            c => {
                d => {
                    e => {
                        f => 'foo!',);

my %subs = (
    hash_ref  => sub {   ref $_[0] eq   ref {}  },array_ref => sub {   ref $_[0] eq   ref []  },true      => sub { ! ref $_[0] &&   $_[0]   },false     => sub { ! ref $_[0] && ! $_[0]   },exist     => sub { 1 },foo       => sub { $_[0] eq 'foo!' },'undef'   => sub { ! defined $_[0] },);

my @paths = (
    [ exist     => qw( a b c d     ) ],# true
    [ hash_ref  => qw( a b c d     ) ],# true
    [ foo       => qw( a b c d     ) ],# false
    [ foo       => qw( a b c d e f ) ],# true
    [ exist     => qw( b c d )       ],# false
    [ exist     => qw( f b c )       ],# false
    [ array_ref => qw( a f )         ],# true
    [ exist     => qw( a f g )       ],# false
    [ 'undef'   => qw( a g )         ],# true
    [ exist     => qw( a b h )       ],# false
    [ hash_ref  => qw( a )           ],# true
    [ exist     => qw( )             ],# false
    );

say Dumper( \%hash ); use Data::Dumper; # just to remember the structure    
foreach my $path ( @paths ) {
    my $sub_name = shift @$path;
    my $sub = $subs{$sub_name};
    printf "%10s --> %-12s --> %s\n",$sub_name,$path ) ? 'true' : 'false';
    }

输出

exist --> a.b.c.d      --> true
  hash_ref --> a.b.c.d      --> true
       foo --> a.b.c.d      --> false
       foo --> a.b.c.d.e.f  --> true
     exist --> b.c.d        --> false
     exist --> f.b.c        --> false
 array_ref --> a.f          --> true
     exist --> a.f.g        --> false
     undef --> a.g          --> true
     exist --> a.b.h        --> true
  hash_ref --> a            --> true
     exist -->              --> false

猜你在找的Perl相关文章