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