使用forEach、map等方法创建一个循环,直到对象(children)的长度等于0。

huangapple go评论89阅读模式
英文:

Make a loop with (forEach, map,...) until length of object (children) is equal to 0

问题

我想在所有对象中将活动元素设置为false。这是我的对象:

const obj = 
  { name: 'obj1'
  , active: true
  , children: 
    [ { name: 'obj2'
      , active: true
      , children: 
        [ { name: 'Obj23'
          , active: true
          , children: [...] 
      } ] } 
    , { name: 'obj3'
      , children: 
        [ { name: 'Obj32'
          , active: true
          , children: [...] 
      } ] } 
    , ...
    } 

我要做的是,对于主对象obj1以及所有子对象和子子对象,我想将active设置为false
重点是,我不知道每个子对象下面可能会有多少子对象。我需要创建一种带有map或类似方法的循环。
当子对象的长度等于0时,我需要停止循环。

编辑:所有解决方案都非常棒。谢谢!

英文:

I want to set the active element to false in all of the objects. This is my object:

const obj = 
  { name: 'obj1'
  , ative: true
  , children: 
    [ { name: 'obj2'
      , ative: true
      , children: 
        [ { name: 'Obj23'
          , ative: true
          , children: [...] 
      } ] } 
    , { name: 'obj3'
      , children: 
        [ { name: 'Obj32'
          , ative: true
          , children: [...] 
      } ] } 
    , ...
    } 

what I have to is, for the main object obj1 and all of the childrens, and sub childres.
I want to set the active to false.
The point is, I don't know how many childrens there can be under each child. I would have to create some type of loop with a map or something of the kind.
I will need to stop looping when the children is equal to 0 (no length)

EDIT: All solutions where really awesome. Thanks

答案1

得分: 1

有两种主要的方法可以使用:

  1. 迭代方法
  2. 递归方法

在大多数情况下,迭代方法在内存和速度方面都更好,因为递归方法需要在调用堆栈中每次调用时额外的O(n)内存。

在迭代方法中,mapforEach数组方法将无用,因为我们不知道长度和何时停止,即使成功使用它们,也将要求我们对遍历的数组进行变异,从而导致副作用。相反,我们将使用一个简单的while循环。

算法:

  • 创建一个堆栈数组并将输入对象放入其中
  • 当堆栈不为空时
    • 让当前元素成为堆栈中弹出的元素
    • 将当前元素的active设置为false
    • 将当前元素的子元素添加到堆栈中以遍历其子元素
  • 返回项目(可选,因为我们正在改变输入对象)

实现:

首先,让我们为输入数据结构创建一个类型:

type Item = {
  name: string;
  active?: boolean;
  children: Item[];
};

现在,函数本身:

const setActive = (data: Item): Item => {
  const stack = [data];

  while (stack.length) {
    const current = stack.pop();

    if (!current) continue;

    current.active = false;

    stack.push(...current.children);
  }

  return data;
};

playground

英文:

There are two main approaches that can be used

  1. Iterative approach
  2. Recursive approach

In most cases, the iterative approach is better in both memory and speed since the recursive approach requires O(n) extra memory for each invocation in the call stack.

In the iterative approach map, and forEach array methods will be useless, since we don't know the length and when to stop, even if manage to use them it will require us to mutate the traversed array which leads to side-effects. Instead, we are going to use a simple while loop.

Algorithm:

  • Create a stack array and put the input object in it
  • While stack is not empty
    • Let current be the popped element from the stack
    • Set current's active to false
    • Add current's children into stack to traverse its children
  • Return item (optional, since we are mutating the input object)

Implementation:

First, let's create a type for the input data structure:

type Item = {
  name: string;
  active?: boolean;
  children: Item[];
};

Now, the function itself:

const setActive = (data: Item): Item => {
  const stack = [data];

  while (stack.length) {
    const current = stack.pop();

    if (!current) continue;

    current.active = false;

    stack.push(...current.children);
  }

  return data;
};

playground

答案2

得分: 1

你也可以使用 JSON.parsereviver function 来实现这个目标:

JSON.parse(JSON.stringify(obj), (key, value) => key === 'ative' ? false : value);
const obj = {
    name: 'obj1',
    ative: true,
    children: [{
        name: 'obj2',
        ative: true,
        children: [{
            name: 'Obj23',
            ative: true,
            children: []
        }]
    },
    {
        name: 'obj3',
        children: [{
            name: 'Obj32',
            ative: true,
            children: []
        }]
    }]
}

const result = JSON.parse(JSON.stringify(obj), (key, value) => key === 'ative' ? false : value);

console.log(result);
英文:

You can also use JSON.parse with reviver function to do this:

JSON.parse(JSON.stringify(obj), (key, value ) => key === 'ative' ? false : value );

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const obj = {
    name: &#39;obj1&#39;,
    ative: true,
    children: [{
        name: &#39;obj2&#39;,
        ative: true,
        children: [{
            name: &#39;Obj23&#39;,
            ative: true,
            children: []
        }]
    },
    {
        name: &#39;obj3&#39;,
        children: [{
            name: &#39;Obj32&#39;,
            ative: true,
            children: []
        }]
    }]
}

const result = JSON.parse(JSON.stringify(obj), (key, value) =&gt; key === &#39;ative&#39; ? false : value);

console.log(result);

<!-- end snippet -->

答案3

得分: 1

我不反对 wonderflame 的看法,如果你不知道你的树会长多大,那么基于堆栈的方法可能更好,但如果你知道你只会深入几个级别,那么可能不需要优化,递归方法更简单。

function deactiveRecursive(obj) {

  return {
    ...obj,
    active: false,
    children: obj.children.map(child => deactivateRecursive(child));
  };
}
英文:

I don't disagree with wonderflame that a stack-based approach is better if you don't know how large your tree will grow, but if you know you will only ever go a few levels deep then the optimization might not be needed, and a recursive approach is simpler.

function deactiveRecursive(obj) {

  return {
    ...obj,
    active: false,
    children: obj.children.map(child =&gt; deactivateRecursive(child));
  };
}

huangapple
  • 本文由 发表于 2023年6月16日 07:57:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486172.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定