【问题标题】:Manipulate a recursive array操作递归数组
【发布时间】:2013-01-02 10:24:55
【问题描述】:

我有一个这样的分层数据结构:

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

【问题讨论】:

标签: javascript jquery angularjs


【解决方案1】:

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

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

【讨论】:

  • 谢谢,这是一个很好的答案。
【解决方案2】:

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

// 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

同样的逻辑,你可以遍历输出数组并在其中添加值。

【讨论】:

  • 谢谢。我选择了另一个答案,因为它还包括 POC;但这个同样正确。
猜你喜欢
  • 2016-01-22
  • 2014-11-16
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-26
相关资源
最近更新 更多