【问题标题】:Filter a javascript tree without mutating the original array在不改变原始数组的情况下过滤 javascript 树
【发布时间】:2018-01-26 17:12:14
【问题描述】:

我正在做一个 react 项目,我需要在不改变原始数组的情况下过滤对象数组

const array = [{
	name: 'bar',
  children: [{
  	name: 'foo',
    children: [{
    	name: 'baz123',
    }, {
    	name: 'baz',
    }]
  }]
}, {
	name: 'shallowKey'
}, {
	name: 'abc'
}];

例如,我只想过滤相关对象及其子对象。

这是jsfiddle

function filterData(data) {
  var r = data.filter(function(o) {
    if (o.children) o.children = filterData(o.children);
    return o.name.length === 3;
  })
  return r;
}

我从 stackoverflow 问题中尝试了该功能,但有没有办法在不改变数据的情况下使用相同的功能。谢谢

【问题讨论】:

    标签: javascript arrays reactjs


    【解决方案1】:

    如果对象中不涉及任何原型或函数,一种简单的复制方法是将原始字符串化并将其解析回对象

    var r= JSON.parse(JSON.stringify(data)).filter(...
    

    【讨论】:

    • 在调试 4 小时后救了我。我认为[...data] 正在完成这项工作,而问题出在其他地方。我错了!
    【解决方案2】:

    数组.filter() 已经创建了一个新数组,您只需修复o.children 发生突变的部分。为此,您可以使用.map() 并简单地使用Object.assign()object spread 复制所有字段,然后将children 分配为通过相同过滤函数的结果:

    function filterData(data) {
      return data
        .filter(obj => obj.name.length === 3) // filter array first
        .map(obj => ({ // then re-map to new objects
          ...obj, // copy shallow fields
          children: obj.children && filterData(obj.children) // filter children
        }));
    }
    

    【讨论】:

    • 可以,但是如果当前对象没有children 属性怎么办。
    • @aspiring_dev 然后它必须重新设计以匹配您的数据结构(任何过滤器功能都需要,无论您是否先克隆它)。这只是基于您的示例。如果您想要一个遍历任何对象树并应用过滤器函数的通用函数,那将是另一种方法。
    【解决方案3】:

    您可以使用扩展运算符或Object.assign() 函数创建原始数组的副本。

    const arrayCopy= [...array] //spread operator
    const arrayCopy = Object.assign({}, array);
    

    否则,正如 Aaron 建议的那样,使用 filter()map()reduce() 函数始终返回一个新数组,而不会改变原始数组。

    【讨论】:

    • [...array] 将创建一个 shallow 副本,因此无法解决这里的问题,Object.assign({}, array) 将创建一个对象而不是数组。
    猜你喜欢
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 2019-10-26
    • 2012-03-24
    • 1970-01-01
    • 2021-06-09
    • 2022-11-12
    • 2019-10-03
    相关资源
    最近更新 更多