javascript – 递归过滤数组的对象

前端之家收集整理的这篇文章主要介绍了javascript – 递归过滤数组的对象前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
用这个打墙,以为我会把它贴在这里,以防某种灵魂碰到一个类似的灵魂.我有一些数据看起来像这样:
  1. const input = [
  2. {
  3. value: 'Miss1',children: [
  4. { value: 'Miss2' },{ value: 'Hit1',children: [ { value: 'Miss3' } ] }
  5. ]
  6. },{
  7. value: 'Miss4',children: [
  8. { value: 'Miss5' },{ value: 'Miss6',children: [ { value: 'Hit2' } ] }
  9. ]
  10. },{
  11. value: 'Miss7',children: [
  12. { value: 'Miss8' },{ value: 'Miss9',children: [ { value: 'Miss10' } ] }
  13. ]
  14. },{
  15. value: 'Hit3',children: [
  16. { value: 'Miss11' },{ value: 'Miss12',children: [ { value: 'Miss13' } ] }
  17. ]
  18. },{
  19. value: 'Miss14',children: [
  20. { value: 'Hit4' },{ value: 'Miss15',children: [ { value: 'Miss16' } ] }
  21. ]
  22. },];

我不知道在运行时层次结构将会有多深,即有多少级对象将有一个子数组.我已经简化了这个例子,实际上我需要将值属性搜索项的数组进行匹配.我们现在假设我在匹配那个value.includes(‘Hit’).

我需要一个返回一个新数组的函数

>每个不具有子项的非匹配对象,或者子层次结构中没有匹配,不应该存在于输出对象中
>具有包含匹配对象的后代的每个对象都应保留
>匹配对象的所有后代应保留

在这种情况下,我正在考虑一个“匹配对象”为具有值属性的值,并且反之亦然.

输出应该如下所示:

  1. const expected = [
  2. {
  3. value: 'Miss1',children: [
  4. { value: 'Hit1',children: [
  5. { value: 'Miss6',]
  6. }
  7. ];

非常感谢任何花时间阅读这篇文章的人,如果我先到达那里,就会发布我的解决方案.

解决方法

使用.filter()和进行递归调用,就像上面的评论所描述的,基本上是你需要的.您只需要在返回之前更新每个.children属性与递归调用的结果.

返回值只是生成的.children集合的.length,所以如果至少有一个,则保留对象.

  1. var res = input.filter(function f(o) {
  2. if (o.value.includes("Hit")) return true
  3.  
  4. if (o.children) {
  5. return (o.children = o.children.filter(f)).length
  6. }
  7. })
  1. const input = [
  2. {
  3. value: 'Miss1',];
  4.  
  5. var res = input.filter(function f(o) {
  6. if (o.value.includes("Hit")) return true
  7.  
  8. if (o.children) {
  9. return (o.children = o.children.filter(f)).length
  10. }
  11. })
  12. console.log(JSON.stringify(res,null,2))

请注意,一个String上的.includes()是ES7,因此可能需要修复旧版浏览器.您可以使用传统的.indexOf(“Hit”)!= -1在其位置.

为了不突变原件,创建一个映射函数来复制一个对象,并在过滤器之前使用它.

  1. function copy(o) {
  2. return Object.assign({},o)
  3. }
  4.  
  5. var res = input.map(copy).filter(function f(o) {
  6. if (o.value.includes("Hit")) return true
  7.  
  8. if (o.children) {
  9. return (o.children = o.children.map(copy).filter(f)).length
  10. }
  11. })

要真正压缩代码,可以这样做:

  1. var res = input.filter(function f(o) {
  2. return o.value.includes("Hit") ||
  3. o.children && (o.children = o.children.filter(f)).length
  4. })

虽然它有点难以阅读.

猜你在找的JavaScript相关文章