Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Perl,从哈希数组创建哈希树的哈希_Arrays_Perl_Hash - Fatal编程技术网

Arrays Perl,从哈希数组创建哈希树的哈希

Arrays Perl,从哈希数组创建哈希树的哈希,arrays,perl,hash,Arrays,Perl,Hash,我有下一个散列数组: my @arr = ( #subways, "0" - superroot {id => "1", parent_id => "0", name => "subway 1"}, #lines {id => "12642", parent_id => "1", name => "no category"}, {id => "12645", parent_id => "1", n

我有下一个散列数组:

my @arr = (
  #subways, "0" - superroot
  {id => "1",     parent_id => "0",     name => "subway 1"},
  #lines
  {id => "12642", parent_id => "1",     name => "no category"},
  {id => "12645", parent_id => "1",     name => "line 1"},
  #cars
  {id => "12646", parent_id => "1",     name => "carriage 1"},
  {id => "12646", parent_id => "12645", name => "carriage 1"},
  {id => "12647", parent_id => "1",     name => "carriage 2"},
  {id => "12647", parent_id => "12645", name => "carriage 2"},
  {id => "12679", parent_id => "1",     name => "separate cars"},
  {id => "12679", parent_id => "12642", name => "separate cars"},
  {id => "12643", parent_id => "1",     name => "ungrouped"},
  {id => "12643", parent_id => "12642", name => "ungrouped"}
);
我注意把它们做成一棵树,就像:

subway->line->carriage
顺便说一下,这里有个问题。正如你们所看到的,这是一个“1”在加倍车厢,但我需要线作为家长的id。 有办法做到这一点吗?

更新 我道歉。我错过了你的最后一段,它解释了一个项目如何在实际价值之外有一个虚假的父项“1”。我添加了一些代码来清理原始数据,并在构建图之前创建每个节点到其真正父节点的映射

使用严格;
使用“全部”警告;
使用Graph::Directed;
我的@arr=(
#地铁,“0”-超级根
{id=>“1”,父\u id=>“0”,name=>“subway 1”},
#线条
{id=>“12642”,父项\u id=>“1”,名称=>“无类别”},
{id=>“12645”,parent_id=>“1”,name=>“line 1”},
#汽车
{id=>“12646”,父_id=>“1”,name=>“carries 1”},
{id=>“12646”,parent_id=>“12645”,name=>“carries 1”},
{id=>“12647”,parent_id=>“1”,name=>“carries 2”},
{id=>“12647”,parent_id=>“12645”,name=>“carries 2”},
{id=>“12679”,父项\u id=>“1”,名称=>“独立车辆”},
{id=>“12679”,父_id=>“12642”,name=>“独立汽车”},
{id=>“12643”,父_id=>“1”,name=>“ungroup”},
{id=>“12643”,父_id=>“12642”,name=>“ungroup”}
);
#清理数据以删除“1”个父项
#
我的%父母;
对于我的$node(@arr){
我的($id,$parent_id)=@{$node}{qw/id parent_id/};
下一步,除非$parent\u id;
$parent{$id}=$parent_id,除非$parent{$id}和$parent{$id}ne 1;
}
#构建图表
#
my$tree=Graph::Directed->new;
对于我的$node(键%parent){
$tree->add_edge($parent{$node}=>$node);
}
#显示数据
#
我的%names=map{@{$}{qw/id name/}}}@arr;
打印$tree->predecessorless_顶点的_树($tree,$);
子打印树{
我的($tree,$root,$indent)=@;
$indent/=0;
printf“%s%s\n”,“x$indent,$names{$root};
为$tree->successivers($root)打印树($tree,$\$indent+1);
}
输出 地铁一号线 第1行 车厢1 车厢2 无类别 分开的车厢 未分组
原始答案 我建议你使用这个模块。树是一个有向图,您只需创建一个图,添加连接(“边”)并查询结果

这个程序正是这样做的。我编写了一个
print_tree
子例程,它从给定的起点以缩进的行显示树。调用
predecessorless_顶点
查找树的所有根:其他节点都没有连接到的节点。在这种情况下,只有一个根,应该有

使用严格;
使用“全部”警告;
使用Graph::Directed;
我的@arr=(
#地铁,“0”-超级根
{id=>“1”,父\u id=>“0”,name=>“subway 1”},
#线条
{id=>“12642”,父项\u id=>“1”,名称=>“无类别”},
{id=>“12645”,parent_id=>“1”,name=>“line 1”},
#汽车
{id=>“12646”,父_id=>“1”,name=>“carries 1”},
{id=>“12646”,parent_id=>“12645”,name=>“carries 1”},
{id=>“12647”,parent_id=>“1”,name=>“carries 2”},
{id=>“12647”,parent_id=>“12645”,name=>“carries 2”},
{id=>“12679”,父项\u id=>“1”,名称=>“独立车辆”},
{id=>“12679”,父_id=>“12642”,name=>“独立汽车”},
{id=>“12643”,父_id=>“1”,name=>“ungroup”},
{id=>“12643”,父_id=>“12642”,name=>“ungroup”}
);
#构建图表
#
my$tree=Graph::Directed->new;
对于我的$node(@arr){
$tree->add_-edge(@{$node}{qw/parent_-id/})如果$node->{parent_-id};
}
#显示结构
#
我的%names=map{@{$}{qw/id name/}}}@arr;
打印$tree->predecessorless_顶点的_树($tree,$);
子打印树{
我的($tree,$root,$indent)=@;
$indent/=0;
printf“%s%s\n”,“x$indent,$names{$root};
为$tree->successivers($root)打印树($tree,$\$indent+1);
}
输出 地铁一号线 无类别 未分组 分开的车厢 车厢2 车厢1 分开的车厢 未分组 第1行 车厢2 车厢1 更新 我道歉。我错过了你的最后一段,它解释了一个项目如何在实际价值之外有一个虚假的父项“1”。我添加了一些代码来清理原始数据,并在构建图之前创建每个节点到其真正父节点的映射

使用严格;
使用“全部”警告;
使用Graph::Directed;
我的@arr=(
#地铁,“0”-超级根
{id=>“1”,父\u id=>“0”,name=>“subway 1”},
#线条
{id=>“12642”,父项\u id=>“1”,名称=>“无类别”},
{id=>“12645”,parent_id=>“1”,name=>“line 1”},
#汽车
{id=>“12646”,父_id=>“1”,name=>“carries 1”},
{id=>“12646”,parent_id=>“12645”,name=>“carries 1”},
{id=>“12647”,parent_id=>“1”,name=>“carries 2”},
{id=>“12647”,parent_id=>“12645”,name=>“carries 2”},
{id=>“12679”,父项\u id=>“1”,名称=>“独立车辆”},
{id=>“12679”,父_id=>“12642”,name=>“独立汽车”},
{id=>“12643”,父_id=>“1”,name=>“ungroup”},
{id=>“12643”,父_id=>“12642”,name=>“ungroup”}
);
#清理数据以删除“1”个父项
#
我的%父母;
对于我的$node(@arr){
我的($id,$parent_id)=@{$node}{qw/id parent_id/};
下一步,除非$parent\u id;
$parent{$id}=$parent_id,除非$parent{$id}和$parent{$id}ne 1;
}
#构建图表
#
my$tree=Graph::Directed->new;
对于我的$node(键%parent){
$tree->add_edge($parent{$node}=>$node);
}
#显示数据
#
我的%names=map{@{$}{qw/id name/}}}@arr;
打印$tree->predecessorless_顶点的_树($tree,$);
子打印树{
我的($tr)
use strict;
use warnings qw( all );
use feature qw( current_sub say );

my @rows = (
   #subways, "0" - superroot
   {id => "1",     parent_id => "0",     name => "subway 1"},
   #lines
   {id => "12642", parent_id => "1",     name => "no category"},
   {id => "12645", parent_id => "1",     name => "line 1"},
   #cars
   {id => "12646", parent_id => "1",     name => "carriage 1"},
   {id => "12646", parent_id => "12645", name => "carriage 1"},
   {id => "12647", parent_id => "1",     name => "carriage 2"},
   {id => "12647", parent_id => "12645", name => "carriage 2"},
   {id => "12679", parent_id => "1",     name => "separate cars"},
   {id => "12679", parent_id => "12642", name => "separate cars"},
   {id => "12643", parent_id => "1",     name => "ungrouped"},
   {id => "12643", parent_id => "12642", name => "ungrouped"}
);

my $tree = { name => "[root]", children => [] };
{
   my %tree = ( 0 => $tree );

   for my $row (@rows) {
      my $node = $tree{ $row->{id} } //= { name => undef, children => [] };
      $node->{name} = $row->{name};

      my $parent_node = $tree{ $row->{parent_id} } //= { name => undef, children => [] };
      push @{ $parent_node->{children} }, $node;
   }
}

# Add depth to nodes.
# use a breadth-first search so that the depth of nodes
# at multiple depths are set to the node's deepest depth.
{
   my @todo = ( [ $tree, 0 ] );
   while (@todo) {
      my ($node, $depth) = @{ shift(@todo) };
      $node->{depth} = $depth;

      ++$depth;
      push @todo, map { [ $_, $depth ] } @{ $node->{children} };
   }
}

# Trim shortcuts to deeper nodes.
{
   my @todo = $tree;
   while (@todo) {
      my $node = shift(@todo);
      my $depth = delete($node->{depth}) + 1;
      @{ $node->{children} } = grep { $_->{depth} == $depth } @{ $node->{children} };
      push @todo, @{ $node->{children} };
   }
}

# Display tree
my $visitor = sub {
   my ($node, $depth) = @_;
   say "  " x $depth, $node->{name};
   __SUB__->($_, $depth+1) for @{ $node->{children} };
};

$visitor->($_, 0) for @$tree;
subway 1
  no category
    separate cars
    ungrouped
  line 1
    carriage 1
    carriage 2