Javascript从一组URL中派生出一个树

时间:2016-12-03 08:47:01

标签: javascript json node.js

伙计们正在尝试创建动态菜单列表。用户可以创建的元素深度没有限制。

我的问题

我的网址设置如下

var json_data = [
    {
        "title" : "Food",
        "path" : "/root",
    },
    {
        "title" : "Cloths",
        "path" : "/root",
    },
    {
        "title" : "Veg",
        "path" : "/root/Food",
    },
    {
        "title" : "Brinjal",
        "path" : "/root/Food/Veg",
    },
    {
        "title" : "T shirt",
        "path" : "/root/Cloths",
    },
    {
        "title" : "Shirt",
        "path" : "/root/Cloths",
    },
    {
        "title" : "Green brinjal",
        "path" : "/root/Food/Veg/Brinjal",
    }
];

我希望titles采用层次结构格式,我最终会以ul > li的形式呈现,以便在前端创建菜单。

层次结构应该是这样的:

[
  {
    "title": "Food",
    "path": "/root",
    "children": [
      {
        "title": "Veg",
        "path": "/root/Food",
        "children": [
          {
            "title": "Brinjal",
            "path": "/root/Food/Veg",
            "children": [
              {
                "title": "Green brinjal",
                "path": "/root/Food/Veg/Brinjal",
                "children": []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "title": "Cloths",
    "path": "/root",
    "children": [
      {
        "title": "T shirt",
        "path": "/root/Cloths",
        "children": []
      },
      {
        "title": "Shirt",
        "path": "/root/Cloths",
        "children": []
      }
    ]
  }
]

我做了什么

    // Add an item node in the tree, at the right position
    function addToTree( node, treeNodes ) {
        // Check if the item node should inserted in a subnode
        for ( var i=0; i<treeNodes.length; i++ ) {
            var treeNode = treeNodes[i];
            // "/store/travel".indexOf( '/store/' )
            if ( node.path.indexOf( treeNode.path + '/' ) == 0 ) {
                addToTree( node, treeNode.children );
                // Item node was added, we can quit
                return;
            }
        }
        // Item node was not added to a subnode, so it's a sibling of these treeNodes
        treeNodes.push({
            title: node.title,
            path: node.path,
            children: []
        });
    }
    //Create the item tree starting from menuItems
    function createTree( nodes ){
        var tree = [];

        for ( var i=0; i<nodes.length; i++ ) {
            var node = nodes[i];
            addToTree( node, tree );
        }
        return tree;
    }

// variable = "json_data" is the set of URLS
var menuItemsTree = createTree( json_data );
console.log(menuItemsTree)

它产生的结果是:

[
  {
    "title": "Food",
    "path": "/root",
    "children": [
      {
        "title": "Veg",
        "path": "/root/Food",
        "children": [
          {
            "title": "Brinjal",
            "path": "/root/Food/Veg",
            "children": [
              {
                "title": "Green brinjal",
                "path": "/root/Food/Veg/Brinjal",
                "children": []
              }
            ]
          }
        ]
      },
      {
        "title": "T shirt",
        "path": "/root/Cloths",
        "children": []
      },
      {
        "title": "Shirt",
        "path": "/root/Cloths",
        "children": []
      }
    ]
  },
  {
    "title": "Cloths",
    "path": "/root",
    "children": []
  }
]

元素"T Shirt""Shirt"被推入食物的孩子:[] ,这些应该在 Cloth的孩子里面:[]

我使用的解决方案取自Here

我试图自己推导出一个算法 - 但它还没有完全正确地点击。如果任何人已经有解决方案,请帮忙。如果我可以自己推导出解决方案,我会在这里分享。 上面的代码是 感谢

1 个答案:

答案 0 :(得分:4)

以下是逻辑。这是 Working Fiddle

&#13;
&#13;
var json_data = [{
  "title": "Food",
  "path": "/root",
}, {
  "title": "Cloths",
  "path": "/root",
}, {
  "title": "Veg",
  "path": "/root/Food",
}, {
  "title": "Brinjal",
  "path": "/root/Food/Veg",
}, {
  "title": "T shirt",
  "path": "/root/Cloths",
}, {
  "title": "Shirt",
  "path": "/root/Cloths",
}, {
  "title": "Green brinjal",
  "path": "/root/Food/Veg/Brinjal",
},{
  "title": "Test cloth",
  "path": "/root/Cloths/Shirt",
}];


// Add an item node in the tree, at the right position
function addToTree(node, treeNodes) {
  var parentNode = GetTheParentNodeChildArray(node.path, treeNodes) || treeNodes;

  parentNode.push({
    title: node.title,
    path: node.path,
    children: []
  });
}

function GetTheParentNodeChildArray(path, treeNodes) {
  for (var i = 0; i < treeNodes.length; i++) {
    var treeNode = treeNodes[i];

    if (path === (treeNode.path + '/' + treeNode.title)) {
      return treeNode.children;
    } 
    else if (treeNode.children.length > 0) {
      var possibleParent = false;

      treeNode.children.forEach(function(item) {
        if (path.indexOf(item.path + '/' + item.title) == 0) {
          possibleParent = true;
          return false;
        }
      });

      if (possibleParent) {
        return GetTheParentNodeChildArray(path, treeNode.children)
      }
    }
  }
}


//Create the item tree starting from menuItems
function createTree(nodes) {
  var tree = [];

  for (var i = 0; i < nodes.length; i++) {
    var node = nodes[i];
    addToTree(node, tree);
  }
  return tree;
}

// variable = "json_data" is the set of URLS
var menuItemsTree = createTree(json_data);
console.log(menuItemsTree);
&#13;
&#13;
&#13;

此逻辑的限制:如果在子节点之前解析父节点,则此逻辑有效,因此建议对列表进行排序 URL(即json_data[])同样如此。这是Sorting-before + tree-structuring-the-sorted

的片段

希望这是有帮助的