【问题标题】:Lookup keys inside a nested hash and then creating a tree of all the keys在嵌套哈希中查找键,然后创建所有键的树
【发布时间】:2014-05-22 17:19:34
【问题描述】:

我在 google 和 stackoverflow 上搜索了如何执行此操作的帮助,但我现在处于一个非常困难且无法执行此操作的地步。

我有一个称为 BigHash 的高度嵌套的哈希作为输入,我有一个更改列表,它也是具有一些键和值的哈希。

我正在尝试在 BigHash 中的 changelist 哈希中查找每个键,并检查值是否匹配,如果不匹配,则我正在尝试创建该键的所有祖先的列表作为字符串分隔;.

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

这是我的变更清单:

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"

这是我的大哈希:

(hash是通过将xml文件转换成hash得到的,有嵌套数组和hash)

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);

【问题讨论】:

  • 在您的$Bighash 中,为什么每个哈希引用都嵌入到数组引用中?这是否与生成 bighash 的方式有关?这最初是 XML 还是其他格式,您使用像 XML::Simple 这样的模块来获得这种结构,而您实际上是在尝试编辑 XML?你确定这是所有相关信息,而且这不是XY Problem
  • 是的,我通过将 XML 文件转换为哈希得到了这个$BigHash,这就是为什么它是这样的:(
  • 您的最终目标是使用这些更新后的值编辑 XML 文件本身吗?注意XML::Simple 已过时,尽管它确实有一些选项可以让您获得更好的输出。然而,最好的选择是使用像 XML::TwigXML::LibXML 这样的模块。如果您与我们分享您的实际数据和目标,您可能会得到更好的建议。
  • 不,我有一个 API,如果我发送该输出字符串,它将使我成为一个新的 XML 文件,很难编辑 XML 文件,因为它必须遵守 xsd 文件中非常严格的模式,并且转换回 XML 的哈希与架构不同,因此我设计了一种更新 XML 文件的新方法。
  • @YouHaveaBigEgo:我鼓励你注意米勒所说的话。我知道回溯您花费大量工作的许多设计选择是一个重大决定,但您最初的问题是因为您首先选择了XML::Simple。它是一个用于产生可靠输出的可怕模块,而您的 “更新 [您的] XML 文件的新方法” 都是因为这个失败。如果您改用XML::LibXML,则该过程非常简单。看看 Ikegami 的帖子,看看它有多么简单:真的就是这么简单!

标签: perl hash


【解决方案1】:
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 这些元素可能不止一次出现。

【讨论】:

  • 嗯。我在PhyCELL 之间看到0 我试图将我的祖先作为字符串列表。像这样:"Phy;CELL;SystemCommon;DopplerEnable=true","Ctrl;SuperCel;Timers;ReqPending=9"
  • 那么您将没有足够的信息来知道哪个元素需要修复,除非您说这些元素中的每一个都只能有一个,在这种情况下,错误在于您包含太多在ForceArray。修复不正确的ForceArray,让“问题”消失。
【解决方案2】:

这会解析 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);

【讨论】:

  • 啊,安装那个模块,现在试试,让我更新你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
  • 2020-07-02
  • 1970-01-01
  • 2017-12-05
  • 2012-04-05
  • 1970-01-01
  • 2013-02-08
相关资源
最近更新 更多