操作递归数组

时间:2013-01-02 10:24:56

标签: javascript jquery angularjs

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

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。也许这些库提供了我可以使用的数组操作函数?

2 个答案:

答案 0 :(得分: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

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

答案 1 :(得分: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);

A fiddle to show it in action