如何将下面的递归函数转换为纯函数
How to turn the following recursive function into a pure function?
以下函数将对象附加到嵌套数组中(通过递归搜索):
function appendDeep (arr, obj, newObj) {
if (arr.indexOf(obj) !== -1) {
arr.splice(arr.indexOf(obj) + 1, 0, newObj)
} else {
arr.map(item => {
if (item.children) spliceDeep(item.children, obj)
})
}
}
示例:
const colors = {
children: [
{
name: 'white',
},
{
name: 'yellow',
children: [
{
name: 'black'
}
]
}
]
}
const color = {
name: 'black'
}
const newColor = {
name: 'brown'
}
appendDeep(colors.children, color, newColor)
结果:
children: [
[
{
name: 'white',
},
{
name: 'yellow',
children: [
{
name: 'black'
},
{
name: 'brown'
}
]
}
]
]
正如您所看到的,appendDeep
返回一个副作用;它修改CCD_ 2。所以我决定返回数组(这样函数就会变得纯粹):
function findDeep (arr, obj) {
if (arr.indexOf(obj) !== -1) {
console.log(arr)
return arr
} else {
arr.map(item => {
if (item.children) findDeep(item.children, obj)
})
}
}
并使用这样的新功能:
const newArr = findDeep(colors.children, color)
newArr.splice(newArr.indexOf(color) + 1, 0, newColor)
但我得到了这个错误:
bundle.js:19893 Uncaught TypeError: Cannot read property 'splice' of undefined
我做错了什么?
(注意:这是CodePen。)
(注意2:console.log(arr)
确实返回嵌套的子级。但由于某种原因,它们在函数之外变成了undefined
。)
您不会在map
中返回递归findDeep
方法。返回该值以使递归工作,因为您的条件分支没有从映射中返回任何内容。因此,您得到的结果是undefined
。JSBin
首先,一个find方法,它将返回请求项所在的数组(作为直接子项)。
function findDeep(arr, obj) {
return arr.map((item) => {
if (item.name === obj.name) {
return arr;
} else if (item.children) {
return findDeep(item.children, obj);
} else {
return undefined;
}
}).reduce((prev, cur) => {
return prev ? prev : cur;
});
}
您可以使用它将项目附加到列表中,但这仍然会修改原始数组:
function appendDeep(arr, color, newColor) {
let found = findDeep(arr, color);
if (found) {
found.splice(found.indexOf(color) + 1, 0, newColor);
}
return arr;
}
如果您不想修改原始数组,事情会变得更加复杂。这是因为push
和splice
等标准数组函数将修改原始数组。没有快速的解决方案,至少我不知道,因为最好你不想克隆比你真正需要的更多的项目。
您不需要克隆black
,但需要克隆包含它的阵列(它可以简单地重用黑色的现有对象。)这意味着黄色的对象也需要克隆(使用克隆的阵列),黄色所在的阵列也需要克隆。但是,同一阵列中的白色不会被修改,也不需要克隆。我还没想好该怎么做。
这是一个使用Array#some
的thisArgs
的提案。
function appendDeep(object, search, insert) {
function iter(a) {
if (a.name === search.name) {
this.children.push(insert);
return true;
}
return Array.isArray(a.children) && a.children.some(iter, a);
}
object.children.some(iter, object);
}
var colors = { children: [{ name: 'white', }, { name: 'yellow', children: [{ name: 'black' }] }] },
color = { name: 'black' },
newColor = { name: 'brown' };
appendDeep(colors, color, newColor);
document.write('<pre>' + JSON.stringify(colors, 0, 4) + '</pre>');
相关文章:
- 如何在JavaScript中将字符串转换为函数引用
- 为什么在单独的函数中应用时转换会闪烁/断断续续(D3)
- Javascript函数,用于将数组转换为“;2-元组”;
- 使用JAVASCRIPT转换货币.可以't通过我的函数设置转换后的输入文本字段的值
- 无法传递Asp.net控件's值转换为javascript函数
- 将JSON字符串转换为函数参数
- 如何传递对'这'转换为函数
- 在Javascript中将字符串转换为函数
- 调用函数时页面未转换
- 如何在将Node异步函数转换为promise时使用Q库
- Jquery移动转换复选框在Jquery onclick函数()中第二次选中不起作用
- JavaScript Othello 左转换和右转换函数
- 无法反转此 HTML 实体转换函数
- 所有过渡完成后的转换函数链接
- 使用 Momentjs 转换函数
- 如何在 javascript 中使字符串转换函数返回值
- ExtJS:关联的idProperty's转换函数未启动
- 转换函数's参数转换为类似数组的对象
- asp到Javascript的转换函数
- 如何在Meteor.js的服务器端转换函数后设置mongo投影