json 树遍历判定子节点?

当前的 JSON 数据结构如下

{
    
    "name": "root",
    "children": [

        {
            "name": "demoA",
            "children": []
        },

        {
            "name": "demoB",
            "children": [

                {
                    "name": "demoB-A",
                    "children": []
                },

                {
                    "name": "demoB-B",
                    "children": []
                },

                {
                    "name": "demoB-C",
                    "children": []
                }

            ]
            
        },

        {
            "name": "demoC",
            "children": []
        }
        
    ]
    
}

有个特殊的需求

  • 每个 JSON 对象都有一个属性: primary (boolean 类型)
  • primary 属性是通过遍历这个 JSON 树来给每个对象设置的
  • 当这个 JSON 对象的 children 有数据, (即 iten.children.length !== 0) 的时候, 需要判断这个 children 数组, 如果该数组内所有元素的 children 都没有数据, 则 primarytrue, 否则为 false
  • 也就是说, 判断 primary 属性是两个条件的拼接 ( children 有数据 && children 里所有对象的 children 没有数据 )

那么, 如何给每个 JSON 对象添加 primary 属性

如果遍历成功, 那么得到的结果是这样的

{

    "name": "root",
    "primary": false,
    "children": [

        {
            "name": "demoA",
            "primary": false,
            "children": []
        },

        {
            "name": "demoB",
            "primary": true,
            "children": [

                {
                    "name": "demoB-A",
                    "primary": false,
                    "children": []
                },

                {
                    "name": "demoB-B",
                    "primary": false,
                    "children": []
                },

                {
                    "name": "demoB-C",
                    "primary": false,
                    "children": []
                }

            ]

        },

        {
            "name": "demoC",
            "primary": false,
            "children": []
        }

    ]

}

HTML 代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script>
            const data = {

                "name": "root",
                "children": [

                    {
                        "name": "demoA",
                        "children": []
                    },

                    {
                        "name": "demoB",
                        "children": [

                            {
                                "name": "demoB-A",
                                "children": []
                            },

                            {
                                "name": "demoB-B",
                                "children": []
                            },

                            {
                                "name": "demoB-C",
                                "children": []
                            }

                        ]

                    },

                    {
                        "name": "demoC",
                        "children": []
                    }

                ]

            }

            function setPrimary() {
                // ...
            }

            setPrimary();

            console.log(data);
        </script>
    </body>
</html>
回复
阅读 815
2 个回答

大概这个意思吧,也可以再优化一下不用循环2次

function fill(node) {
  node.primary = !!node.children.length && node.children.every(child => !child.children.length);
  node.children.forEach(child => fill(child));
}

// fill(data);

补充一个解决方案

function hasChildren(node) {
    return node.children.length !== 0;
}

function recursion(node, fun) {
  node = fun(node);
  if (hasChildren(node)) {
      for (const child of node.children) {
          recursion(child, fun)
      }
  }
}

recursion(data, (node) => {
  node.primary = false;
  if (hasChildren(node)) {
      node.primary = true;
      for (const item of node.children) {
          if (hasChildren(item)) {
              node.primary = false;
              break;
          }
      }
  }
  return node;
})
推荐问题
宣传栏