JavaScript - 操作嵌套的多维对象数组

时间:2014-01-22 20:52:37

标签: javascript arrays object multidimensional-array d3.js

我正在使用D3创建一个用户可以操作的树形布局。我有一个对象,其中包含应用程序中其他对象的子数组,让用户可以选择不同的路径。

我开始使用没有ID的对象,并使用D3来添加ID:

    var source = {
    "name": "Top Condition",
    "state": "condition",
    "children": [{
            "name": "Open",
            "dest": "true",
            "state": "open"
    }, {
            "name": "Sub Condition 1",
            "dest": "false",
            "state": "condition",
            "children": [{
                    "name": "Open",
                    "dest": "true",
                    "state": "open"
            }, {
                    "name": "Open",
                    "dest": "false",
                    "state": "open"
            }, {
                    "name": "Open",
                    "dest": "unknown",
                    "state": "open",
                    "children": [{
                            "name": "Open",
                            "dest": "true",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "dest": "false",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "dest": "unknown",
                            "state": "open"
                    }]
            }]
    },{
            "name": "Sub Condition 2",
            "dest": "unknown",
            "state": "condition"
            ,"children": [{
                    "name": "Open",
                    "dest": "true",
                    "state": "open"
            }, {
                    "name": "Open",
                    "dest": "false",
                    "state": "open"
            }, {
                    "name": "Sub Condition 3",
                    "dest": "false",
                    "state": "condition",
                    "children": [{
                            "name": "Open",
                            "dest": "true",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "dest": "false",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "dest": "unknown",
                            "state": "open"
                    }]

            }]
    }]
}




// Compute the new tree layout.
var nodes = tree.nodes(source).reverse(),
        links = tree.links(nodes);

// Update the nodes with IDs
var node = svg.selectAll("g.node")
    .data(nodes, function (d) {
    return d.id || (d.id = ++i);
});

这是我正在使用的对象之后D3上面的魔术(手动添加ID,不完全是D3生成的内容):

source = {
    "name": "Top Condition",
    "id": 1,
    "state": "condition",
    "children": [{
            "name": "Open",
            "id": 2,
            "dest": "true",
            "state": "open"
    }, {
            "name": "Sub Condition 1",
            "id": 3,
            "dest": "false",
            "state": "condition",
            "children": [{
                    "name": "Open",
                    "id": 4,
                    "dest": "true",
                    "state": "open"
            }, {
                    "name": "Open",
                    "id": 5,
                    "dest": "false",
                    "state": "open"
            }, {
                    "name": "Open",
                    "id": 6,
                    "dest": "unknown",
                    "state": "open",
                    "children": [{
                            "name": "Open",
                            "id": 14,
                            "dest": "true",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "id": 15,
                            "dest": "false",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "id": 16,
                            "dest": "unknown",
                            "state": "open"
                    }]
            }]
    },{
            "name": "Sub Condition 2",
            "id": 7,
            "dest": "unknown",
            "state": "condition"
            ,"children": [{
                    "name": "Open",
                    "id": 8,
                    "dest": "true",
                    "state": "open"
            }, {
                    "name": "Open",
                    "id": 9,
                    "dest": "false",
                    "state": "open"
            }, {
                    "name": "Sub Condition 3",
                    "id": 10,
                    "dest": "false",
                    "state": "condition",
                    "children": [{
                            "name": "Open",
                            "id": 11,
                            "dest": "true",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "id": 12,
                            "dest": "false",
                            "state": "open"
                    }, {
                            "name": "Open",
                            "id": 13,
                            "dest": "unknown",
                            "state": "open"
                    }]

            }]
    }]
}

所以我想要做的是拥有一个带有对象ID的函数,并将一个'children'数组添加到一个对象中(或删除一个子数组)嵌套在源代码中的某个地方。

因此,例如,对于包含id:13的对象,我想将其添加到对象:

    var children = [{
        "name": "Open",
        "dest": "true",
        "state": "open"
}, {
        "name": "Open",
        "dest": "false",
        "state": "open"
}, {
        "name": "Open",
        "dest": "unknown",
        "state": "open"
}];

此外,我需要能够执行相反的操作并从ID 10中删除子数组。

然后我会通过D3运行它来获取输入的任何节点的ID并重新渲染树。

这可能吗?我怎么能完成它?我愿意使用下划线或其他库,但根据我对文档的理解无法弄清楚。

1 个答案:

答案 0 :(得分:3)

这里最简单的方法可能是走树,创建一个单独的地图,通过id:

来引用对象
// set up the map
var idMap = {};

// recursive collection function
function collect(item) {
    idMap[item.id] = item;
    // recurse through the children, if any
    (item.children || []).map(collect);
}

// kick off
collect(source);

现在你有一个像{ 1: <Object>, 2: <Object>, ...}这样的地图,它很简单,可以添加或删除具有单独功能的子项,例如:

function updateChildren(id, children) {
    var o = idMap[id];
    o.children = children;
}

你可能也想在这里做其他事情,例如根据新孩子(或删除孩子),合并新老孩子等更新id地图。