2014-05-22 21 views
0

我搜索了如何做到这一点,在谷歌和stackoverflow,我现在在一个点,我相当卡住,无法做到这一点这个。在嵌套散列中查找键然后创建所有键的树

我有一个称为BigHash作为输入哈希繁重嵌套散列,我有一个变更列表,这也是哈希有一些键和值。

我想在BigHash中查找更改列表中的每个键,并检查值是否匹配,如果不匹配,则尝试创建该键的所有祖先的列表作为字符串用;分开。

这是我的更改列表和预期输出。

这是我的改变列表:

my $changelist = { 
'ReqPending' => '9', 
'DopplerEnable' => 'true', 
'BSColorCode' => '7' 
} 

这是我期望的输出:

(注输出字符串中以逗号分隔的数组中的字符串中的每个元素是实际的祖先。在与变更表该密钥的值链接变更列表关键的树)

@Output = "Ctrl;SuperCel;Timers;ReqPending=9", "Phy;CELL;SystemCommon;Config;DopplerEnable=true", "Phy;CELL;SystemCommon;PhysicalCell;BSColorCode=7" 

这是我的大哈希:

(散列是通过将一个XML文件转换成一个散列得到的,它嵌套数组和哈希)

my $Bighash= { 
'Ctrl' => [ 
    { 
     'SuperCel' => [ 
        { 
        'Config' => [ 
             { 
             'Retry' => '3', 
             'Context' => '3' 
             } 
            ], 
        'Timers' => [ 
             { 
             'ReqPending' => '2', 
             'RelocationReqPending' => '2' 
             } 
            ] 
        } 
      ] 
    } 
    ], 
    'xmlns' => 'http://www.somewebsite.com/oam', 
    'Phy' => [ 
     { 
     'CELL' => [ 
       { 
       'SystemCommon' => [ 
         { 
         'Config' => [ 
             { 
             'SrsOn' => 'true', 
             'WindowLength' => '2', 
             'DopplerEnable' => 'false', 
             'WindowSize' => '3', 
             } 
            ], 
         'PhysicalCellID' => '0', 
         'ColorConfig' => [ 
             { 
             'AckNackFeedback' => '1', 
             'frameAssignment' => '1', 
             'SframePattern' => '7' 
             } 
            ], 
         'Ports' => '2', 
         'AntennaCount' => '2', 
         'NumberOfConnections' => '8', 
         'PhysicalCell' => [ 
               { 
                'NwColorCode' => '0', 
                'BSColorCode' => '0' 
               } 
               ], 
         'CellIdentity' => '0', 
         'IdentityGroup' => '0', 
         'OverrideEnableFlag' => 'false' 
         } 
        ], 
       'Dedicated' => [ 
        { 
         'SoundingRs' => [ 
          { 
           'ConfigDedicatedRel10' => [ 
            { 
             'Format' => [ 
              { 
              'DomainPosition' => '0', 
              'TransmissionComb' => '0', 
              'Shift' => '1', 
              'Port' => '1', 
              'Bandwidth' => '0' 
              } 
             ], 
            } 
           ] 
          } 
         ], 
         'Numerology' => [ 
          { 
           'profileNumber' => '0' 
          } 
         ]              
        } 
       ] 
      } 
     ] 
    } 
] 

}

你能帮助我吗?

我已经写了类似这样的东西,但它不正确,我没有得到它。

sub recursive { 
    $hash = shift; 

    foreach my $key1 (keys %$hash) { 
    if (ref($hash->{$key1}) eq "HASH") { 
     if ($var ne "") { 
     $var = join(";", $var, $key1); 
     } 
     else { 
     $var = $key1; 
     } 
     recursive($hash->{$key1}); 
    } 
    elsif (ref($hash->{$key1}) eq "ARRAY") { 
     $tem = @{ $hash->{$key1} }; 
     if ($var ne "") { 
     $var = join(";", $var, $key1); 
     } 
     else { 
     $var = $key1; 
     } 
     foreach $item (@{ $hash->{$key1} }) { 
     if (ref($item) eq "HASH") { 
      #$var = join (";",$var,$key1); 
      recursive($item); 
     } 
     else { 
     } 
     } 
    } 
    else { 
     if ($var ne "") { 
     $temp = $var; 
     $var = join(";", $var, $key1); 
     print $var. "\n"; 
     #$var=$temp; 
     } 
     else { 
     $var = $key1; 
     undef($var); 
     } 
    } 
    } 
} 

recursive($BigHash); 
+0

在'$ Bighash',为什么每个哈希裁判嵌入数组引用?这是否与生成bighash有关?原来是XML还是其他一些格式,并且您使用了像XML :: Simple这样的模块来获得这种结构,而您实际上是在尝试编辑XML?你确定这是所有相关信息,并且这不是[XY问题](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? – Miller

+0

是的,我通过将XML文件转换为哈希来得到这个'$ BigHash',这就是为什么它是这样的: – YouHaveaBigEgo

+0

你最终的目标是用这些更新的值来编辑XML文件本身吗?注意[:XML: :Simple'](https://metacpan.org/pod/XML::Simple)已经过时了,不过它确实有更好的输出选项,但最好的选择是使用一个模块,如[XML :: Twig '](https://metacpan.org/pod/XML::Twig)或['XML :: LibXML'](https://metacpan.org/pod/XML::LibXML)。如果你分享了你的实际数据和我们的目标,你可能会得到更好的建议。 – Miller

回答

0
sub find_missing_changes { 
    my $changelist = shift; 
    my @output; 

    local *_helper = sub { 
     my $data = pop; 

     my $reftype = ref($data) 
     or return; 

     if ($reftype eq 'ARRAY') { 
     for my $i (0..$#$data) { 
      _helper(@_, $i, $data->[$i]); 
     } 
     } 

     elsif ($reftype eq 'HASH') { 
     for my $k (keys(%$data)) { 
      if (exists($changelist->{$k}) && $data->{$k} ne $changelist->{$k}) { 
       push @output, join(';', @_, $k)."=".$changelist->{$k}; 
      } 

      _helper(@_, $k, $data->{$k}); 
     } 
     } 
    }; 

    _helper(@_); 

    return @output; 
} 

print "$_\n" for find_missing_changes($changelist, $Bighash); 

输出:

Phy;0;CELL;0;SystemCommon;0;Config;0;DopplerEnable=true 
Phy;0;CELL;0;SystemCommon;0;PhysicalCell;0;BSColorCode=7 
Ctrl;0;SuperCel;0;Timers;0;ReqPending=9 

如果不需要数组下标,你不应该告诉XMLin可以有这些元素中的一种以上发生。

+0

嗯。我在'Phy'和'CELL'之间看到一个'0'我试图让我的祖先成为一串字符串。像这样:''Phy; CELL; SystemCommon; DopplerEnable = true“,”Ctrl; SuperCel; Timers; ReqPending = 9“ – YouHaveaBigEgo

+0

然后你就没有足够的信息去知道哪个元素需要修复,除非你在那里说可以只是这些元素中的每一个的元素中的一个,在这种情况下,您的''ForceArray'中包含太多的错误。修复不正确的'ForceArray'使“问题”消失。 – ikegami

0

这解析XML文件,执行在%$changelist的变化,并保存更改:

use XML::LibXML qw(); 

my $parser = XML::LibXML->new(no_network => 1); 
my $doc = $parser->parse_file($qfn); 

for my $node ($doc->findnodes('//*')) { 
    for my $attr_name (keys(%$changelist)) { 
     if ($node->hasAttribute($attr_name)) { 
     $node->setAttribute($changelist->{$attr_name}); 
     } 
    } 
} 

$doc->toFile($qfn); 
+1

啊,安装该模块并现在尝试它,让我更新你。 – YouHaveaBigEgo