将平面数据结构转换为树 [英] Convert a flat datastructure into a tree

查看:182
本文介绍了将平面数据结构转换为树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个散列数组。阵列中的每个元素都是分层树中的一个节点,并且对父节点的父对象具有参考数据。我将在树中有成千上万个节点...基本上一个未知的节点必须转换成JSON(如下所示),以便与 http://bl.ocks.org/robschmuecker/7880033



更新:position_id是异端树。 placement_id是父亲的position_id(邻接参照树)。



更新:这是完整的AoH Data :: Dumper结果,嵌套集和邻接结果来自修改版本的 DBIx :: Tree :: NestedSet (自定义)

  $ VAR1 = [
{
'lft'=> '673',
'id'=> '109',
'date_created'=> '2015-08-15',
'level'=> '7',
'user_id'=> '13',
'placement_id'=> '11',
'position_id'=> '13',
'status'=> '1',
'struct_id'=> '1',
'rght'=> '684'
},
{
'placement_id'=> '13',
'position_id'=> '22',
'status'=> '1',
'struct_id'=> '1',
'rght'=> '679',
'lft'=> '674',
'date_created'=> '2015-08-15',
'id'=> '116',
'level'=> '8',
'user_id'=> '22'
},
{
'user_id'=> '101',
'level'=> '9',
'id'=> '200',
'date_created'=> '2015-08-15',
'lft'=> '675',
'rght'=> '676',
'struct_id'=> '1',
'status'=> '1',
'position_id'=> '101',
'placement_id'=> '22'
},
{
'date_created'=> '2015-08-15',
'id'=> '201',
'level'=> '9',
'user_id'=> '374',
'lft'=> '677',
'struct_id'=> '1',
'rght'=> '678',
'placement_id'=> '22',
'position_id'=> '374',
'status'=> '1'
},
{
'lft'=> '680',
'user_id'=> '95',
'level'=> '8',
'id'=> '117',
'date_created'=> '2015-08-15',
'status'=> '1',
'position_id'=> '95',
'placement_id'=> '13',
'rght'=> '681',
'struct_id'=> '1'
}
];

这是目标,对于这个例子,我需要结束:

  {
name:13,
children:[
{
名称:22,
children:[
{
name:101
},
{
name :374
}
]
},
{
name:95
}
]

您还可以看到我要到达的格式(减大小):
http://bl.ocks.org/robschmuecker/7880033#flare.json



我的失败方法包括各种尝试,循环遍历散列数组,以创建一个递归哈希散列,然后可以与 JSON Perl模块来创建我需要的实际JSON。

解决方案

 我的$ data = [
{position_id => 123,placement_id => undef},
{position_id => 456,placement_id => 123},
{position_id => 789,placement_id => 123},
#...
];

我的$根;
{
我的%recs_by_name;
我的%children_by_parent_name;
为$ row(@ $ data){
我的$ name = $ row-> {position_id};
my $ parent_name = $ row-> {placement_id};

我的$ rec = {
name => $ name,
};

push @ {$ children_by_parent_name {$ parent_name //'root'}},$ rec;
$ recs_by_name {$ name} = $ rec;
}

$ roots = delete($ children_by_parent_name {root})|| [];

为我的$ name(keys(%children_by_parent_name)){
my $ children = $ children_by_parent_name {$ name};
if(my $ rec = $ recs_by_name {$ name}){
$ rec-> {children} = $ children;
} else {
die(Parent $ name not exist.\\\
);
push @ $ roots,@ $ children;
}
}
}

print(Dumper($ roots));

测试。



你似乎有您可以使用的每个节点的深度(级别)。如果您的数据通过增加深度进行排序,则可以使用更简单的代码。


I have an array of hashes. Each element in the array is a node in a hierarchical tree and has referential data for who the parent is. I will have thousands and hundreds of thousands of nodes in the tree... essentially an unknown set of nodes has to be converted to JSON (shown below) for use with http://bl.ocks.org/robschmuecker/7880033

UPDATE: position_id is a node in the heretical tree. placement_id is the parent's position_id (adjacency referential tree).

UPDATE: Here's the full AoH Data::Dumper result with Nested Set and Adjacency result from a modified version of DBIx::Tree::NestedSet (custom).

$VAR1 = [
          {
            'lft' => '673',
            'id' => '109',
            'date_created' => '2015-08-15',
            'level' => '7',
            'user_id' => '13',
            'placement_id' => '11',
            'position_id' => '13',
            'status' => '1',
            'structure_id' => '1',
            'rght' => '684'
          },
          {
            'placement_id' => '13',
            'position_id' => '22',
            'status' => '1',
            'structure_id' => '1',
            'rght' => '679',
            'lft' => '674',
            'date_created' => '2015-08-15',
            'id' => '116',
            'level' => '8',
            'user_id' => '22'
          },
          {
            'user_id' => '101',
            'level' => '9',
            'id' => '200',
            'date_created' => '2015-08-15',
            'lft' => '675',
            'rght' => '676',
            'structure_id' => '1',
            'status' => '1',
            'position_id' => '101',
            'placement_id' => '22'
          },
          {
            'date_created' => '2015-08-15',
            'id' => '201',
            'level' => '9',
            'user_id' => '374',
            'lft' => '677',
            'structure_id' => '1',
            'rght' => '678',
            'placement_id' => '22',
            'position_id' => '374',
            'status' => '1'
          },
          {
            'lft' => '680',
            'user_id' => '95',
            'level' => '8',
            'id' => '117',
            'date_created' => '2015-08-15',
            'status' => '1',
            'position_id' => '95',
            'placement_id' => '13',
            'rght' => '681',
            'structure_id' => '1'
          }
        ];

THIS IS THE GOAL, For this example I need to end up with:

{
    "name": "13",
    "children": [
        {
            "name": "22",
            "children": [
                {
                    "name": "101"
                },
                {
                    "name": "374"
                }
            ]
        },
        {
            "name": "95"
        }
    ]
}

You can also see the format I am trying to arrive at here (minus size): http://bl.ocks.org/robschmuecker/7880033#flare.json

My failed approach(es) included various attempts at looping through the array of hashes to create a recursive Hash of Hashes that can then be used with the JSON Perl module to create the actual JSON I need.

解决方案

my $data = [
   {  position_id => 123, placement_id => undef },
   {  position_id => 456, placement_id => 123 },
   {  position_id => 789, placement_id => 123 },
   # ...
];

my $roots;
{
   my %recs_by_name;
   my %children_by_parent_name;
   for my $row (@$data) {
      my $name        = $row->{position_id};
      my $parent_name = $row->{placement_id};

      my $rec = {
         name => $name,
      };

      push @{ $children_by_parent_name{$parent_name // 'root'} }, $rec;
      $recs_by_name{$name} = $rec;
   }

   $roots = delete($children_by_parent_name{root}) || [];

   for my $name (keys(%children_by_parent_name)) {
      my $children = $children_by_parent_name{$name};
      if ( my $rec = $recs_by_name{$name} ) {
         $rec->{children} = $children;
      } else {
         die("Parent $name doesn't exist.\n");
         push @$roots, @$children;
      }
   }
}

print(Dumper($roots));

Tested.

You appear to have the depth of each node available to you (level). Simpler code could be used if your data was sorted by increasing depths.

这篇关于将平面数据结构转换为树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆