从父菜单递归查找所有子级

时间:2018-08-27 12:02:04

标签: javascript recursion

我有这样的JSON结构:

[
    {"menuId":"1001","depth":"1","parentId":"0"},
    {"menuId":"1002","depth":"1","parentId":"0"},
    {"menuId":"1003","depth":"2","parentId":"1001"},
    {"menuId":"1004","depth":"2","parentId":"1001"},
    {"menuId":"1005","depth":"3","parentId":"1003"}, 
    {"menuId":"1006","depth":"3","parentId":"1004"}, 
    {"menuId":"1007","depth":"4","parentId":"1006"}, 
    {"menuId":"1008","depth":"4","parentId":"1006"}, 
    {"menuId":"1009","depth":"5","parentId":"1008"}
]

因此,我需要一个(可能)递归函数,该函数将找到一个menuId的所有子项,甚至是深层嵌套的子项。

因此,我想 findChildrens('1004') 。这应该返回以下结果:

['1006', '1007', '1008', '1009']

因为每个菜单都可以引用回 1004 。不需要特定的订单。深度可能会不定地上升。

4 个答案:

答案 0 :(得分:3)

您可以通过检查parentId并获得结果集menuId来采取迭代和递归的方法。然后也添加新的子代。

function getChildren(array, id) {
    return array.reduce((r, { menuId, parentId }) => {
        if (parentId === id) {
            r.push(menuId, ...getChildren(array, menuId));
        }
        return r;
    }, []);
}

var data = [{ menuId: "1001", depth: "1", parentId: "0" }, { menuId: "1002", depth: "1", parentId: "0" }, { menuId: "1003", depth: "2", parentId: "1001" }, { menuId: "1004", depth: "2", parentId: "1001" }, { menuId: "1005", depth: "3", parentId: "1003" }, { menuId: "1006", depth: "3", parentId: "1004" }, { menuId: "1007", depth: "4", parentId: "1006" }, { menuId: "1008", depth: "4", parentId: "1006" }, { menuId: "1009", depth: "5", parentId: "1008" }],
    result = getChildren(data, '1004');

console.log(result);

答案 1 :(得分:2)

您可以像这样使用普通的递归。

  var k = 
         [{"menuId":"1001","depth":"1","parentId":"0"},
          {"menuId":"1002","depth":"1","parentId":"0"},
          {"menuId":"1003","depth":"2","parentId":"1001"},
          {"menuId":"1004","depth":"2","parentId":"1001"},
          {"menuId":"1005","depth":"3","parentId":"1003"}, 
          {"menuId":"1006","depth":"3","parentId":"1004"}, 
          {"menuId":"1007","depth":"4","parentId":"1006"}, 
          {"menuId":"1008","depth":"4","parentId":"1006"}, 
          {"menuId":"1009","depth":"5","parentId":"1008"}]
        var res = [];
          var findChildren = function(id){
            k.forEach(obj => {
              if(obj.parentId === id){
                  res.push(obj.menuId);
        		  findChildren(obj.menuId)
        		}
        	})
        }
    
        findChildren('1004');
        console.log(res);

答案 2 :(得分:1)

使用Array.prototype.mapArray.prototype.filter的简单替代方法:

const data = [{"menuId":"1001","depth":"1","parentId":"0"},{"menuId":"1002","depth":"1","parentId":"0"},{"menuId":"1003","depth":"2","parentId":"1001"},{"menuId":"1004","depth":"2","parentId":"1001"},{"menuId":"1005","depth":"3","parentId":"1003"}, {"menuId":"1006","depth":"3","parentId":"1004"}, {"menuId":"1007","depth":"4","parentId":"1006"}, {"menuId":"1008","depth":"4","parentId":"1006"}, {"menuId":"1009","depth":"5","parentId":"1008"}];

function findChildren(id) {

    const menuIds = data.filter(({parentId}) => parentId == id).map(({menuId}) => menuId);

    return menuIds.concat(...menuIds.map(findChildren));

}

console.log(findChildren(1004));

答案 3 :(得分:0)

您可以使用filter()方法来使用递归函数来查找子代。

ES6中的DEMO

const findChildrens = (data, menuId, oputArr, callback)  => {
    let filterArr = data.filter(({ parentId }) => parentId == menuId);
    if (filterArr.length) {
      	//Concat array with filtered data
        oputArr = [...oputArr, ...filterArr.map(({ menuId }) => menuId)];
      	//Recursive call for again search next node data
        findChildrens(data, oputArr[oputArr.length - 1], oputArr, callback);
    } else {
      	//If find 
        callback(oputArr);
    }
}

const arr =[{"menuId":"1001","depth":"1","parentId":"0"},{"menuId":"1002","depth":"1","parentId":"0"},{"menuId":"1003","depth":"2","parentId":"1001"},{"menuId":"1004","depth":"2","parentId":"1001"},{"menuId":"1005","depth":"3","parentId":"1003"},{"menuId":"1006","depth":"3","parentId":"1004"},{"menuId":"1007","depth":"4","parentId":"1006"},{"menuId":"1008","depth":"4","parentId":"1006"},{"menuId":"1009","depth":"5","parentId":"1008"}];

//Call find children function for 1004
findChildrens(arr, '1004', [], (res) => {
    console.log('result for 1004',res);
});

//Call find children function 1001
findChildrens(arr, '1001', [], (res) => {
    console.log('result for 1001',res);
});
.as-console-wrapper {max-height: 100% !important;top: 0;}

ES5中的DEMO

var filterArr = [];

function findChildrens(data, menuId, oputArr, callback) {
    filterArr = data.filter(function(o) {
        return o.parentId == menuId;
    });

    if (filterArr.length) {
    
        //Concat array with filtered data
        oputArr = [].concat.apply(oputArr, filterArr.map(function(o) {
            return o.menuId;
        }));
        //Recursive call for again search next node data
        findChildrens(data, oputArr[oputArr.length - 1], oputArr, callback);
    } else {
        //If find 
        callback(oputArr);
    }
}

var arr = [{"menuId":"1001","depth":"1","parentId":"0"},{"menuId":"1002","depth":"1","parentId":"0"},{"menuId":"1003","depth":"2","parentId":"1001"},{"menuId":"1004","depth":"2","parentId":"1001"},{"menuId":"1005","depth":"3","parentId":"1003"},{"menuId":"1006","depth":"3","parentId":"1004"},{"menuId":"1007","depth":"4","parentId":"1006"},{"menuId":"1008","depth":"4","parentId":"1006"},{"menuId":"1009","depth":"5","parentId":"1008"}];

//Call find children function for 1004
findChildrens(arr, '1004', [], function(res){
    console.log('result for 1004', res);
});

//Call find children function 1001
findChildrens(arr, '1001', [], (res) => {
    console.log('result for 1001', res);
});
.as-console-wrapper {max-height: 100% !important;top: 0;}