首页 > 用Js实现非递归无限分类

用Js实现非递归无限分类

自定义一组数据,内容任意,要求做到将无序的多级别数据格式化成数
这是boss给我出的一道题,他是PHP,而我还只是个js新手
之前以递归的形势完成了这道题,然后boss就让我再用非递归的办法做一次

以下是我自定义的数据,以层次编码的方式表述数据间的关系:
最终完成的效果是用数组嵌套,类似于:

var data=[
    {id:'01',name:"A"},
    {id:'0101',name:"A1"},
    {id:'0103',name:"A3"},
    {id:'0102',name:"A2"},
    {id:'0202',name:"B2"},    
    {id:'0301',name:"C1"},
    {id:'0303',name:"C3"},
    {id:'0302',name:"C2"},
    {id:'02',name:"B"},
    {id:'0201',name:"B1"},  
    {id:'020101',name:"B11"},
    {id:'030103',name:"C13"},
    {id:'03010301',name:"C131"},
    {id:'03010302',name:"C132"},
    {id:'0203',name:"B3"},
    {id:'03',name:"C"},
    {id:'030101',name:"C11"},
    {id:'030102',name:"C12"},  
    {id:'0301030101',name:"C1311"}, 
    {id:'0301030201',name:"C1321"}  
];
[
    [A,[A1,A2,A3]],
    [B,[B1,B2,B3]],
    [C,[
        C1,C2,C3,
            [C11,C12,C13
                [c131,c132]
            ]
        ]
    ]          
]    

或者其他能够把树表示清楚的格式也可以

这只是一个PHP的boss给我这个JS新人出的一道小考题
没有实际的用途,所以数据也是任意的,只要能达到效果就可以
只是我数据结构的知识实在太过贫乏,做了很久都无法达到效果
在网上查了很多资料,大多是关于php的无限极非递归实现,看起来很吃力,也没什么头绪

PS:下面简述一下我的思路:
1、 将同一级别的数据组成数组,放入group数组的对应位置,最后获取级别长度
2、 for循环由下至上,将子节点数据插入父节点的数组中,保存父节点,作为下次循环的子节点
最后在代码实现的过程中,卡在了当有多个子节点时,怎么确定各个父节点的位置,如

   [[B11],[C11,C12]]

B11需要插入到上一级的B数组中,并对应B1,而[C11,C12]需要插入到C数组中,并对应C1,如果到更深层次,要确定的位置量跟多,具体怎么实现,实在没有头绪,感觉我的思路应该不对

如果诸位有什么思路,或者能建议我去了解哪方面的资料,都可以说一说,感谢大家了!


因为第一次提问需要审核,在等审核的时候我把php的解决方案研究了一下
最后用JS模仿成功了,PHP方案代码如下:
http://www.oschina.net/code/s...

<?php
 
/**
 * 此方法由@Tonton 提供
 * http://my.oschina.net/u/918697
 * @date 2012-12-12 
 */
function genTree5($items) { 
    foreach ($items as $item) 
        $items[$item['pid']]['son'][$item['id']] = &$items[$item['id']]; 
    return isset($items[0]['son']) ? $items[0]['son'] : array(); 
} 
 
/**
 * 将数据格式化成树形结构
 * @author Xuefen.Tong
 * @param array $items
 * @return array 
 */
function genTree9($items) {
    $tree = array(); //格式化好的树
    foreach ($items as $item)
        if (isset($items[$item['pid']]))
            $items[$item['pid']]['son'][] = &$items[$item['id']];
        else
            $tree[] = &$items[$item['id']];
    return $tree;
}
 
$items = array(
    1 => array('id' => 1, 'pid' => 0, 'name' => '江西省'),
    2 => array('id' => 2, 'pid' => 0, 'name' => '黑龙江省'),
    3 => array('id' => 3, 'pid' => 1, 'name' => '南昌市'),
    4 => array('id' => 4, 'pid' => 2, 'name' => '哈尔滨市'),
    5 => array('id' => 5, 'pid' => 2, 'name' => '鸡西市'),
    6 => array('id' => 6, 'pid' => 4, 'name' => '香坊区'),
    7 => array('id' => 7, 'pid' => 4, 'name' => '南岗区'),
    8 => array('id' => 8, 'pid' => 6, 'name' => '和兴路'),
    9 => array('id' => 9, 'pid' => 7, 'name' => '西大直街'),
    10 => array('id' => 10, 'pid' => 8, 'name' => '东北林业大学'),
    11 => array('id' => 11, 'pid' => 9, 'name' => '哈尔滨工业大学'),
    12 => array('id' => 12, 'pid' => 8, 'name' => '哈尔滨师范大学'),
    13 => array('id' => 13, 'pid' => 1, 'name' => '赣州市'),
    14 => array('id' => 14, 'pid' => 13, 'name' => '赣县'),
    15 => array('id' => 15, 'pid' => 13, 'name' => '于都县'),
    16 => array('id' => 16, 'pid' => 14, 'name' => '茅店镇'),
    17 => array('id' => 17, 'pid' => 14, 'name' => '大田乡'),
    18 => array('id' => 18, 'pid' => 16, 'name' => '义源村'),
    19 => array('id' => 19, 'pid' => 16, 'name' => '上坝村'),
);
echo "<pre>";
print_r(genTree5($items));
print_r(genTree9($items));
 

我的模仿如下:

var data=[
    {id:1,pId:0,cId:1,name:"A"},
    {id:11,pId:1,cId:1,name:"A1"},
    {id:12,pId:1,cId:2,name:"A2"},
    {id:13,pId:1,cId:3,name:"A3"},
    {id:22,pId:2,cId:2,name:"B2"},    
    {id:31,pId:3,cId:1,name:"C1"},
    {id:32,pId:3,cId:2,name:"C2"},
    {id:33,pId:3,cId:3,name:"C3"},
    {id:2,pId:0,cId:2,name:"B"},
    {id:21,pId:2,cId:1,name:"B1"},  
    {id:36,pId:31,cId:3,name:"C13"},
    {id:37,pId:36,cId:1,name:"C131"},
    {id:23,pId:2,cId:3,name:"B3"},
    {id:3,pId:0,cId:3,name:"C"},
    {id:34,pId:31,cId:1,name:"C11"},
    {id:35,pId:31,cId:2,name:"C12"},  
    {id:38,pId:37,cId:1,name:"C1311"}   
];
function treeMenu(tree){
    var newTree = [];
    var tmp = [];
    var item = [];
    //遍历数组,建立临时扁平数据
    for(var x in tree){
        item[tree[x].id] = [tree[x].name];
    }
    //遍历数组,同时获取每个对象的父节点和子节点数据
    for(var x in tree){
        var parentId = tree[x].pId; 
        var childId = tree[x].cId;
        //该对象的父元素节点在临时数据中的对应位置有数据存在时
        //说明这是一个二级以上的节点
        //将它的数据传递给父节点对应的子节点位置
        if(item[parentId]){
            item[parentId][childId] = item[tree[x].id];
        }
        //如果没有,说明这是一个一级节点,直接传递给最终结果
        else{
            newTree.push(item[tree[x].id]);
        }
        //因为传递的值为引用值,所以当处理数据时
        //对子节点进行操作后,同样会反映到父节点中,最后体现在最终结果里        
    }
    item = null; // 解除临时数据
    return newTree;
}
console.log(treeMenu(data));

最后达到了预期要求,如果大家对这个有兴趣,欢迎来提提意见建议!

【热门文章】
【热门文章】