使用javascript在递归中存储树级别的层次结构

时间:2017-09-12 18:09:23

标签: javascript arrays json recursion tree

function formSelectedTree(totaldata, selectedIds) {
    if (!Array.isArray(totaldata)) return;
    for (var item of totaldata) {
        if ((!item.children || item.children.length === 0)) {
            selectedIds.map(function(id, index) {
                if (parseInt(item.id) === parseInt(id)) {
                    item.isSelected = true
                    item.open = true
                }
            })
        } else {
            this.formSelectedTree(item.children, selectedIds);
        }
    }
    return totaldata
}

参数:

  • 对象的totaldata-array数组(在json下面找到)
  • selectedIds:字符串数组(叶子节点的Id)[“1749”,“1747”]

上面的递归函数是像json对象一样迭代树。 我们从后端获取叶子节点的ID,根据这些ID,我们应该选择叶子节点并从父级别扩展树形结构。

使用'isSelected'布尔属性处理选择 使用'open'boolean属性来处理树节点的扩展。

我能够为叶节点设置这些属性。但是面临难以为其父/子父级别设置open = true。

请找到以下示例json对象

{
    "Data": [{
        "id": 1745,
        "parentId": null,
        "isSelected": false,
        "open": false,
        "children": [{
            "id": 1746,
            "parentId": 1745,
            "isSelected": false,
            "open": false,
            "children": [{
                    "id": 1747,
                    "parentId": 1746,
                    "isSelected": false,
                    "open": false
                },
                {
                    "id": 1748,
                    "parentId": 1746,
                    "isSelected": false,
                    "open": false,
                    "children": [{
                        "id": 1749,
                        "parentId": 1748,
                        "isSelected": false,
                        "open": false
                    }]
                }
            ]
        }]
    }]
}

有人可以帮我解决这个难题。

谢谢

2 个答案:

答案 0 :(得分:0)

此示例将parentNode属性添加到遇到的每个节点,并在找到给定的选定叶节点后使用它来设置所有祖先的“open”属性。

function formSelectedTree(totaldata, selectedIds, parentNode) {
  if (!parentNode) parentNode = false;
  if (!Array.isArray(totaldata)) return;
  for (var item of totaldata) {
    // set the parentNode property for each item we traverse
    item.parentNode = parentNode;
    if ((!item.children || item.children.length === 0)) {
        selectedIds.map(function(id, index) {
            if (parseInt(item.id) === parseInt(id)) {
                item.isSelected = true
                item.open = true
                
                // since this is a leaf item that is selected/open, all its ancestors should be open too
                var p = item.parentNode;
                while (p) {
                  p.open = true;
                  // travel up through the hierarchy until parentNode doesn't exist (top level)
                  p = p.parentNode;
                }
            }
        })
    } else {
        this.formSelectedTree(item.children, selectedIds, item);
    }
  }
  return totaldata;
}

答案 1 :(得分:0)

如果id使用Set,您可以使用不同的方法,如果所有ID都已处理,则使用Array#some短路。

对于所有子节点的更新,您可以使用另一个递归函数,该函数适用于实际节点以及子节点的回调。

如果您将字符串作为id,我建议在创建集合之前将它们转换为数据类型。



function formSelectedTree(totaldata, selectedIds) {

    function update(o) {
        o.isSelected = true;
        o.open = true;
        o.children && o.children.forEach(update);
    }

    if (!Array.isArray(totaldata)) {
        return;
    }
    return totaldata.some(function (item) {
        if (selectedIds.has(item.id)) {
            update(item);
            selectedIds.delete(item.id);
            return !selectedIds.size;
        }
        return item.children && formSelectedTree(item.children, selectedIds);
    });
}

var data = { "Data": [{ "id": 1745, "parentId": null, "isSelected": false, "open": false, "children": [{ "id": 1746, "parentId": 1745, "isSelected": false, "open": false, "children": [{ "id": 1747, "parentId": 1746, "isSelected": false, "open": false }, { "id": 1748, "parentId": 1746, "isSelected": false, "open": false, "children": [{ "id": 1749, "parentId": 1748, "isSelected": false, "open": false }] }] }] }] };

formSelectedTree(data.Data, new Set([1749, 1747]));

console.log(data);

.as-console-wrapper { max-height: 100% !important; top: 0; }