Home > Back-end >  How to modify an array by link inside function?
How to modify an array by link inside function?

Time:07-13

I have the following function:

  public recursiveFilterLayers(node: LayerNode[]): LayerNode[] {
    const validItem = node.filter(
      (i) => i.visible === true || i.visible === undefined
    );

    validItem.forEach((i) => {
      if (i.children) i.children = this.recursiveFilterLayers(i.children);
    });

    return validItem;
  }

And using:

data = recursiveFilterLayers(data);

How to rewrite this function to use without return like:

recursiveFilterLayers(data);

I mean pass the reference to data array.

CodePudding user response:

Array.filter returns a copy, so you can't mutate the original array with it. Instead, you will need to explicitly iterate over the array using a loop.

It's tempting to use splice to remove individual values, but this has O(n²) behaviour because splice has to copy all subsequent elements one place backwards every time an element is removed.

A better approach is to keep a read and a write index, and perform a single splice at the end to cut off the end of the array:

function recursiveFilterLayers(node) {
  let readIndex;
  let writeIndex = 0;
  for (readIndex = 0; readIndex < node.length; readIndex  ) {
    const element = node[readIndex];
    if (element.visible === true || element.visible === undefined) {
      node[writeIndex] = element;
      if (element.children) {
        recursiveFilterLayers(element.children);
      }
      writeIndex  ;
    }
  }

  node.splice(writeIndex, readIndex - writeIndex);
}

const data = [
  {visible: true},
  {},
  {visible: false},
  {
    children: [{visible: false}, {visible: true}],
  },
];
recursiveFilterLayers(data);
console.log(data);

CodePudding user response:

In javascript, primitives are passed by value, and Objects are passed by "copy of a reference". You don't have to return at all, a function can modify the content.

Although you used a filter that copies the parameter's content thus won't modify anything. Instead, we can use forEach like following.

public recursiveFilterLayers(nodes: LayerNode[]): LayerNode[] {
    nodes.forEach(n=>{
        if((n.visible === true || n.visible === undefined) && n.children){
            this.recursiveFilterLayers(n.children);
        }
    });
    return;
}
  • Related