Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使递归函数不变异?_Javascript_Ecmascript 6 - Fatal编程技术网

Javascript 使递归函数不变异?

Javascript 使递归函数不变异?,javascript,ecmascript-6,Javascript,Ecmascript 6,我有一个递归函数,它按id删除一个项,如果这个项嵌套在子数组中,它会将它向上移动一级,它基本上是一种菜单结构。当一个项目被删除时,子项目不会被丢弃,而是保留在原始对象中 现在,它接受一个“数据”参数并对其进行操作,但是 我想知道是否有可能将其转换为返回全新数组的函数,从而保持参数不变? 这就是函数 function removeId(data, id, parent = null) { data.forEach((o, i) => { if (o.id && o

我有一个递归函数,它按id删除一个项,如果这个项嵌套在子数组中,它会将它向上移动一级,它基本上是一种菜单结构。当一个项目被删除时,子项目不会被丢弃,而是保留在原始对象中

现在,它接受一个“数据”参数并对其进行操作,但是 我想知道是否有可能将其转换为返回全新数组的函数,从而保持参数不变?

这就是函数

function removeId(data, id, parent = null) {
  data.forEach((o, i) => {
    if (o.id && o.id === id) {
      if (parent) {
        o.children.forEach(c => parent.children.push(c));
      }
      data.splice(i, 1);
      return true;
    } else if (o.children) {
      removeId(o.children, id, o);
    }
  });
}
这是使用的测试数据

const data = [
  {
    id: 2,
    children: [
      {
        id: 1,
        children: []
      }
    ]
  },
  {
    id: 3,
    children: [],
  }
]
函数的调用方式如下

data = removeId(data, itemIdToDelete)
预期输出是一个新的(不可变)数组,其结构与前一个数组相同,但删除的项(嵌套)除外

这是运行方法并传递要删除的2的id后的预期输出

const data = [
  {
    id: 1,
    children: []
  },
  {
    id: 3,
    children: [],
  }
]
我试过了
  • 使用Array.reduce()或Array.filter()转换函数,但它会破坏递归性,每次都返回未定义的

编辑:这不仅仅是一个简单的深度克隆问题,还涉及到逻辑问题,例如检查父对象是否有子对象。

您可以使用
reduce
方法完成此操作,并在每个递归级别上创建新数组

const data=[{“id”:2,“children”:[{“id”:1,“children”:[]}]},{“id”:3,“children”:[]}]
函数removeId(数据,id){
返回数据。减少((r,e)=>{
//创建当前对象的浅层副本
常量o=Object.assign({},e);
//如果对象具有子对象属性
//使用递归调用创建子级的嵌套副本
//其中data param现在将是当前元素的子元素
如果(如儿童){
o、 children=removeId(即children,id);
}
//如果当前元素的id等于目标id
//将其子级推(展开)到电流累加器-r
//这将取决于当前的递归级别
//否则只需将当前对象推到浅拷贝-o即可
如果(id==e.id){
r、 推动(…o.儿童)
}否则{
r、 推(o)
}
//回流蓄能器
返回r;
}, [])
}
console.log(removeId(数据,1))
console.log(removeId(数据,3))

log(removeId(data,2))
相反,您可以使用生成器执行此操作,从而避免所有推送操作<代码>收益率*然后可用于将子数据提升一个级别

const data=[{“id”:2,“children”:[{“id”:1,“children”:[]}]},{“id”:3,“children”:[]}]
函数*\u removeId(数据,id){
对于(数据的o){
如果(o.id==id)产生*o.children;
赋值({},o,{children:removeId(o.children,id)});
}
}
函数removeId(数据,id){
返回数组.from(_removeId(data,id));
}
日志(removeId(数据,1));
日志(removeId(数据,2));

日志(removeId(数据,3))您可以通过递归创建数组来实现这一点

const data = [
{
id: 2,
children: [
  {
    id: 1,
    children: []
  }
]
},
{
id: 3,
children: [],
}
];

function removeData(myarray, removable) {
 var branch = [];
 var datas= {};
 myarray.forEach((dat, key) => {
  if(dat.id != removable) {
     datas.id = dat.id;
     datas.children = [];
  }

 if(dat.children.length >0) {
       var children =   removeData(dat.children, removable);
       if(children && datas.id) {
            datas.children = children;
        } else {
             datas = children[0];
        } 
    }
    if(datas.children || datas.id) {
        branch.unshift(datas);
        datas ={};
    }   
 });
 return branch;
 }

 console.log(JSON.stringify(removeData(data, 2)));

预期的输出是什么?如何调用此函数?@Notflip-bu您的
removeId
方法需要3个参数??什么是
这个.links
?可能重复@VLAZ No,OP不仅仅是cloningid:1的对象仍然包含在第一个控制台中。log()我看到了吗?需要做的是,必须从数组或数组中的子对象中删除传递id的对象。然后孩子们必须向上移动,这基本上是一个菜单结构OK,但这不是你说的
而且如果这个项目嵌套在孩子数组中,它会向上移动。
我的意思是向上移动一级,如果不清楚,很抱歉,我会编辑这个问题。@Notflip我仍然不确定你想要的结果是什么。你能提供一个答案吗examples@NenadVracar-您不需要在函数声明中使用
parent
,因为您没有使用它。