简体   繁体   中英

What is the fastest way to concatenate results of a recursive function into an array in Javascript?

As the title says I'm searching for the most efficient way to create a flat array output from a recursive function.

The following example produces the correct result but it is kind of slow as it has to create a temporary concatenated array of points for each level of recursion.

class QuadTree {

  // ...
  // some other methods
  // ...

  get points() {
    if (this.divided) {
      // concatenate and return points of all subtrees
      return this.subtrees[0].points.concat(
        this.subtrees[1].points,
        this.subtrees[2].points,
        this.subtrees[3].points
      );
    }
    // return _points array of this quadtree
    return this._points;
  }
}

Is there a way to speed this up?

I would think that this kind of problem is quite common when working with nested/treelike datastructures but I have not found a satisfying solution.

The only thing that I can think of is to replace your accessor property with a function (or perhaps add the function alongside it) and pass the target array in so that it can be filled in directly. Something like:

class QuadTree {

  // ...
  // some other methods
  // ...

  getDividedPoints(target = []) {
    this.subtrees[0].getDividedPoints(target);
    this.subtrees[1].getDivdedPoints(target);
    this.subtrees[2].getDivdedPoints(target);
    this.subtrees[3].getDivdedPoints(target);
    return target;
  }

  get points() {
    if (this.divided) {
      return this.getDividedPoints([]);
    }
    // return _points array of this quadtree
    return this._points;
  }
}

Or if subtrees is a normal array, getDividedPoints could be:

getDividedPoints(target = []) {
  this.subtrees.forEach(subtree => subtree.getDividedPoints(target));
  return target;
}

Otherwise, since I assume you want to copy this.subtrees[0].points (rather than inserting into it), concat 's going to be pretty good.

If the subtrees may or may not be divided, you'll need the if in the function. And I just belatedly noticed the name of the class. :-) So I'd probably just make the four calls:

getPoints(target) {
  if (this.divided) {
    target = target || [];
    this.subtrees[0].getPoints(target);
    this.subtrees[1].getPoints(target);
    this.subtrees[2].getPoints(target);
    this.subtrees[3].getPoints(target);
    return target;
  }
  if (target) {
    target.push.apply(target, this._points);
    return target;
  }
  return this._points; // <== If you're really okay with giving this
                       // to the caller (you were in your original code)
}

get points() {
  return this.getDividedPoints([]);
}

...or any of several other spins on that basic idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM