英文:
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
有两种主要的方法可以使用:
- 迭代方法
- 递归方法
在大多数情况下,迭代方法在内存和速度方面都更好,因为递归方法需要在调用堆栈中每次调用时额外的O(n)
内存。
在迭代方法中,map
和forEach
数组方法将无用,因为我们不知道长度和何时停止,即使成功使用它们,也将要求我们对遍历的数组进行变异,从而导致副作用。相反,我们将使用一个简单的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;
};
英文:
There are two main approaches that can be used
- Iterative approach
- 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
tofalse
- 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;
};
答案2
得分: 1
你也可以使用 JSON.parse
与 reviver 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: '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);
<!-- 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 => deactivateRecursive(child));
};
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论