Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在javascript中将数组转换为嵌套对象_Javascript_Arrays_Node.js_Tree - Fatal编程技术网

在javascript中将数组转换为嵌套对象

在javascript中将数组转换为嵌套对象,javascript,arrays,node.js,tree,Javascript,Arrays,Node.js,Tree,我有典型的组织结构层次结构。比如说 D,E is reporting to B. B,C is reporting to A. A是最上面的节点。但我接收到的数据是一个平面数组,其属性指向父对象 [{ name: "A", parent: null }, { name: "B", parent: "A" }, { name: "C", parent: "A" }, {

我有典型的组织结构
层次结构
。比如说

D,E is reporting to B. B,C is reporting to A.
A是最上面的节点。但我接收到的数据是一个平面数组,其属性指向父对象

    [{
      name: "A",
      parent: null
    },
    {
      name: "B",
      parent: "A"
    },
    {
      name: "C",
      parent: "A"
    },
    {
      name: "D",
      parent: "B"
    },
    {
      name: "E",
      parent: "B"
    }]
但我想将其转换为
单个嵌套对象
。根节点具有嵌入子节点的children属性,每个子节点都有自己的children属性,如下所示

    {
      name: "A",
      children: [{
        name: "C"
        children: [{
          name: "D"
        },{
          name: "E"
        }]
      },{
        name: "C"
      }]
    }

如何在javascript中高效地执行此操作

您可以使用while循环执行此操作:

var data = [
    { name: "A", parent: null },
    { name: "B", parent: "A" },
    { name: "C", parent: "A" },
    { name: "D", parent: "B" },
    { name: "E", parent: "B" }
];

var root = data.find(function(item) {
    return item.parent === null;
});

var tree = {
    name: root.name
};

var parents = [tree];
while (parents.length > 0) {
    var newParents = [];
    parents.forEach(function(parent) {
        var childs = data.filter(function(item) {
            return item.parent == parent.name
        }).forEach(function(child) {
            var c = { name: child.name };
            parent.children = parent.children || [];
            parent.children.push(c);
            newParents.push(c);
        });
    });
    parents = newParents;
}

console.log(tree);

与其他解决方案不同,它使用单个循环-数据的顺序不重要-示例与问题的顺序不同

var peeps = [
    { name: "D", parent: "B" }, 
    { name: "B", parent: "A" },
    { name: "A", parent: null }, 
    { name: "C", parent: "A" }, 
    { name: "E", parent: "B" }
];

var tree;
var obj = {};
peeps.forEach(function (peep) {
    var name = peep.name,
        parent = peep.parent,
        a = obj[name] || { name: name };
    if (parent) {
        obj[parent] = obj[parent] || { name: parent };
        obj[parent].children = obj[parent].children || [];
        obj[parent].children.push(a);
    } else {
        tree = obj[name];
    }
    obj[name] = obj[name] || a;
});
console.log(tree);

此解决方案以Jaromanda X'为特色,并添加了一些功能

  • Array.prototype.reduce
    而不是
    Array.prototype.forEach
    ,因为需要临时变量和返回值

  • r[a.name].children的内容将被保留并分配给
    a.children

  • 节点
    a
    被分配给
    r[a.name]
    。因此,节点对象的所有属性保持不变,如
    prop1
    <代码>prop5
  • 根节点被分配到
    r.
    以供以后使用

  • var数据=[
    {名称:“D”,父项:“B”,prop1:'prop1'},
    {名称:“B”,父级:“A”,prop2:'prop2'},
    {name:“A”,父项:null,prop3:'prop3'},
    {名称:“C”,父级:“A”,prop4:'prop4'},
    {名称:“E”,父项:“B”,prop5:'prop5'}
    ],
    tree=data.reduce(函数(r,a){
    a、 children=r[a.name]&&r[a.name]。children;
    r[a.name]=a;
    如果(a.父母){
    r[a.parent]=r[a.parent]| |{};
    r[a.parent]。children=r[a.parent]。children | |[];
    r[a.parent].children.push(a);
    }否则{
    r、 _uA=a;
    }
    返回r;
    }, {})._;
    
    document.write(“”+JSON.stringify(tree,0,4)+“”)如果提供的数组顺序不正确,则此操作将失败。var data=[,{name:“B”,parent:“A”},{name:“A”,parent:null},{name:“C”,parent:“A”},{name:“D”,parent:“B”},{name:“E”,parent:“B”}];例如,它会崩溃。@SimonBrahan不,它不会失败。您忘记删除数据中的逗号了。@madox2,它应该是
    console.log(tree)
    ,对吗?你能解释一下这是怎么回事吗?您没有在任何地方修改树对象,但结果是在树中。我很困惑。@espeirasbora你是对的,那是一种打字错误。我批准编辑以修复
    a=obj[name]| |{name:name}
    在这里,您可以使用peep代替新对象,并将
    a
    替换为
    obj[name]
    ,完成
    obj[name]=obj[name]|peep
    其中
    a
    只使用
    obj[name]
    现在您可以删除最后一行
    obj[name]=obj[name]|a@NinaScholz对此不确定。你试过了吗?首先,输出格式不包括
    parent
    属性。此外,在代码的疯狂背后还有一种方法,允许输入数据以任意顺序排列。请看我的答案。关于属性
    父属性
    ,您是对的,我只包括所有属性。(op没有问他们)。我有类似的代码,使用reduce,并且reduce变量上有一个“特殊”属性,甚至称之为
    \uuu
    -我认为这可能会让op有点不知所措-但是我仍然使用我的逻辑返回请求的确切结构:pSorry for necropposting,但是..如果有一些根注释,而不是只有一个,其中parent为Null,那么您的两个代码都不起作用。@DenimTornado,请参阅第2部分了解多个根元素。@NinaScholz很酷,它可以工作,请稍等,您能澄清一下“.Null.children;”part在末尾吗?
    r[a.parent]
    创建了一个带有
    'Null'
    null
    as string,因为所有键都是字符串)as key,这是根对象的已知符号。这用于获取它的子对象。