【问题标题】:Create deep hash mapping in perl在 perl 中创建深度哈希映射
【发布时间】:2014-05-06 08:45:45
【问题描述】:

下面是我的哈希代码

#!/usr/bin/perl
use warnings;
use JSON::PP; # Just 'use JSON;' on most systems
my %name = (
          'sl' => {
                    'fsd' => {
                               'conf' => {
                                           'ul' => '/sl/fsd/conf/ul',
                                           'si' => '/sl/fsd/conf/si',
                                           'ho1' => '/sl/fsd/conf/ho1'
                                         }
                             }
                  },
          're' => {
                    'fsd' => {
                               'cron' => {
                                           'README' => '/re/fsd/cron/README'
                                         },
                               'bin' => {
                                          'db' => {
                                                    'smart.p_add_tag' => '/re/fsd/bin/db/smart.p_add_tag',
                                                    'smart.p_tag_partition' => '/re/fsd/bin/db/smart.p_tag_partition',
                                                    'smart.p_add_tag_type' => '/re/fsd/bin/db/smart.p_add_tag_type'
                                                  }
                                        },
                               'doc' => {
                                          'SMART' => '/re/fsd/doc/SMART',
                                          'README' => '/re/fsd/doc/README'
                                        },
                               'data' => {
                                           'README' => '/re/fsd/data/README'
                                         },
                               'conf' => {
                                           'al1' => '/re/fsd/conf/al1',
                                           'file' => '/re/fsd/conf/file',
                                           'ho' => '/re/fsd/conf/ho',
                                           'al3' => '/re/fsd/conf/al3',
                                           'hst' => '/re/fsd/conf/hst',
                                           'us' => '/re/fsd/conf/us',
                                           'README' => '/re/fsd/conf/README',
                                           'al2' => '/re/fsd/conf/al2'
                                         }
                             }
                  }
        );




(my $root) = keys %name;

my %nodes = ();
my %tree  = ();
my @queue = ($root);

list_children(\%name, \@queue, \%nodes) while @queue;

my $tree = build_tree($root, \%nodes);

my $json = JSON::PP->new->pretty; # prettify for human consumption

print $json->encode($tree);

sub list_children {
  my $adjac = shift;
  my $queue  = shift;
  my $nodes  = shift;

  my $node = shift @$queue;

  my @children = keys %{$adjac->{$node}};

  @children = grep { ! exists $nodes->{$_}} @children;

  $nodes->{$node} = \@children;

  push @$queue, @children;
}

sub build_tree {
  my $root  = shift;
  my $nodes = shift;

  my @children;
  for my $child (@{$nodes->{$root}}) {
    push @children, build_tree($child, $nodes);
  }

  my %h = ('text'     => $root,
           'children' => \@children);

  return \%h;
}

我正在尝试输出 JSONified 哈希,但它最多只能遍历两个级别。而我需要它遍历所有父节点的最后一个子节点。有人可以帮助实现这一目标吗?

下面是电流输出

{
   "text" : "sl",
   "children" : [
      {
         "text" : "fsd",
         "children" : []
      }
   ]
}

【问题讨论】:

  • 你试过什么?如果您发布一些代码以及运行该代码时获得的结果,您将获得更多帮助。只问“给我解决方案”不是一个好主意。
  • 感谢保罗的建议。我试图遍历散列,然后将每个二级元素分配为子元素,但它没有按预期工作,而且我没有将散列分配给散列的想法。请帮忙。
  • 预期的输出不是你想的那样。尝试 Data::Dumper 并转储值 - 哈希不能有多个同名键。
  • 您要创建图表吗?
  • 嗨@rahulsagar,您可以发布带有上述问题描述的实际代码,以便人们可以帮助您更轻松地调试它。

标签: perl hash perl-data-structures


【解决方案1】:

通常,转换散列,然后 然后 json-ing 不是最有效的想法,因为您将进行一次遍历来转换散列,而 JSON 将进行一次遍历到 json-化它,JSON 是哈希的一种转换。

但是,JSON 通常是用 XS 完成的,这意味着至少第二次遍历更快。那和 JSON 行为是标准化的。

use 5.016;
use strict;
use warnings;
use Data::Dumper ();
use JSON;

my $hash
    =  {
  'Foods' => {
    'fruits' => {
      'orange' => '1',
      'apple' => '2',
    },
    'Vegetables' => {
      'tomato' => '3',
      'carrot' => '1',
      'cabbage' => '2',
    }
  }
};

sub descend { 
    my ( $structure, $block ) = @_;
    my $res;
    while ( my ( $k, $v ) = each %$structure ) { 
        $block->( $structure, $k, $v );
        if ( ref( $v ) eq 'HASH' ) { 
            $res = descend( $v, $block );
        }
    }
    return $res;
}

my $new  = {};
my $curr = $new;

descend( $hash => sub { 
    my ( $lvl, $k, $v ) = @_;
    my $node = { text => $k };
    $curr->{children} //= [];
    push $curr->{children}, $node;

    if ( ref( $v ) eq 'HASH' ) { 
        $curr = $node;
    }
    else { 
        $node->{children} = { text => $v };
    }
});

# allow for the root-level special case, and retrieve the first child. 
$new = $new->{children}[0];

say Data::Dumper->Dump( [ $new ], [ '$new' ] );
say JSON->new->encode( $new );

【讨论】:

  • 感谢代码,但它似乎无法正常识别孩子
  • @rahulsagar,这正是if ( ref( $v ) eq 'HASH' ) 的分支。如果它是散列,则它不是叶节点,否则它是,并且“孩子”被分配一个散列,其中一个键“文本”指向该值,如您最初所示。我怀疑这可能是节点相似的javascript方面的问题,但我们有时有一个“孩子”节点数组,有时有一个节点。
猜你喜欢
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多