3

我有一个分层数据结构,例如:

var tree = [ {foo: 1, children:[
    {foo: 2, children:[
        {foo: 13, children:[]},
        {foo: 14, children:[]}
    ]}, 
    {foo: 3, children:[]}, 
    {foo: 4, children:[]}
]}, 

{foo: 5, children:[
    {foo: 6, children:[]}, 
    {foo: 8, children:[]}
]}, 

{foo: 9, children:[
    {foo: 10, children:[]}, 
    {foo: 11, children:[]}, 
    {foo: 12, children:[]}
]} ];

树可以是任何深度。

为了重新定位树中的特定对象(包括它的子对象),我可以简单地编写:

// Move object from [0, 0, 1] to [2, 1]
var obj = tree[0]['children'][0]['children'][1];
tree[0]['children'][0]['children'].splice(1, 1);
tree[2]['children'].splice(1, 0, obj);

但我无法对一般情况进行编程:

给定两组坐标,将对象从 [i1, i2, ..., im] 重新定位到 [j1, j2, ..., jn]。

我想要一些关于如何构造这个递归算法的提示。虽然这是一个纯 Javascript 问题,但我应该注意我的应用程序使用 AngularJS 和 jQuery。也许这些库提供了我可以使用的数组操作函数?

4

2 回答 2

3

主要问题是您必须访问任意深度的属性。你可以使用的是一个在某种意义上是递归的循环:

// a is the input set

var arr = tree;  // start at the root
for(var i = 0; i < a.length - 1; i++) {  // stop one too early
  arr = arr[ a[i] ].children;
}
// now, arr is the array you want to splice, so
// you can splice the object and store it in a temporary
// place

使用相同的逻辑,您可以遍历输出数组并在那里添加值。

于 2013-01-02T10:50:40.347 回答
3

进行这种树遍历的一种方法是使用一个变量来存储对您导航到的树部分的引用,一次导航一个层。我们可以写一个遍历函数如下:

var traverseTree = function(tree, coord) {

  var current = tree;

  // Loop through the coordinates moving one at a time, no error handling
  // what happens if the node doesn't exist?
  for(var i = 0; i < coord.length; ++i) {
    current = current[coord[i]].children;
  }      

  // Return the node
  return current;
}

然后我们可以编写描述为两个函数的功能,一个提取节点的方法和一个插入节点的方法:

var extractNodeFromTree = function(tree, coord) {

  // We don't want to traverse the whole way
  var last = coord.pop();

  // Traverse to the parent
  var parent = traverseTree(tree, coord);

  // Extract the element using the last coordinate
  return parent.splice(last, 1)[0];
}

var insertNodeIntoTree = function(tree, coord, node) {

  // Same as last method
  var last = coord.pop();
  var parent = traverseTree(tree, coord);

  // Insert node to the specified position
  current.splice(last, 0, node);

}

您可以使用以下功能:

var node = extractNodeFromTree(tree, [0, 0, 1]);
insertNodeIntoTree(tree, [2, 1], node);

一个在行动中展示它的小提琴

于 2013-01-02T10:51:13.607 回答