【问题标题】:Javascript Recursion: remove level with only one childJavascript递归:删除只有一个孩子的级别
【发布时间】:2019-03-13 22:37:55
【问题描述】:

给定以下数据结构:

[  
  {  
     "name":"root",
     "children":[  
        {  
           "name":"de",
           "children":[  
              {  
                 "name":"de",
                 "children":[
                    {  
                       "name":"project-1",
                       "children":[  
                       ]
                    },
                    {  
                       "name":"project-2",
                       "children":[  
                       ]
                    }
                 ]
              }
           ]
        }
     ]
  }
]

预期:

[
  {
     "name":"project-1",
     "children":[
     ]
  },
  {
     "name":"project-2",
     "children":[
     ]
  }
]

如果只有一个孩子,我想删除一个关卡。在此示例中,我想要一个新数组,该数组仅包含“根”级别的子级,而没有根本身。

我会用reduce 做到这一点,但我仍然无法将reduce 与递归结合使用。有什么想法吗?

【问题讨论】:

  • 抱歉,您能否提供一个您希望得到的结果数组的示例?谢谢!
  • 请提供预期的数组。您编写的代码和当前结果。
  • 编辑了描述中的预期结果

标签: javascript recursion ecmascript-6


【解决方案1】:

之后您可以简单地使用映射和展平数组。

.map(o => o.children).flat()

编辑:找出真正的问题后更新答案
您仍然可以使用映射和展平逻辑,但以递归方式。

function removeSingleChildElms (o) {
  if (!o.children) return

  if (o.children.length === 1) {
      return o.children.map(removeSingleChildElms).flat()
  } else {
    return o.children
  }
}

编辑2: 一些解释:问题是将对象数组转换为不同对象的数组。我不选择reduce,因为问题不关心兄弟元素之间的关系/逻辑。这只是关于转换,因此地图将足够好。

问题要求“跳过”有 1 个孩子的对象。这是重复出现的部分,意思是:如果你看到一个满足这个条件的对象,你会更深入地进行映射。在任何其他有效条件下,孩子保持不变(其他情况)

【讨论】:

  • 这不包括有孩子的孩子的数据
  • 他说''我想要一个新数组,它只包含“根”级别的子级,而没有根本身。''。这是删除根级别。在输入和输出部分“等”保持不变
  • 这只是示例。算法应该适用于所有输入。依此类推,表明应该应用此算法的其他层。 OP还表示要使用array.reduce和recursion,表示要处理所有层
  • 更新了我的答案
【解决方案2】:

可以通过将任务分为两部分来轻松进行树转换:

  1. 用于转换单个节点的函数
  2. 一个用于转换节点数组的函数

要转换单个节点,我们写transform1

  • 如果有没有个子节点,我们找到了叶子节点,返回单例节点
  • 如果只有一个子节点,则删除节点并返回其唯一子节点的变换
  • 否则节点有多个子节点,调用我们的第二个函数transformAll
const transform1 = ({ children = [], ...node }) =>
  children.length === 0         // leaf
    ? [ node ]
: children.length === 1         // singleton
    ? transform1 (...children)
: transformAll (children)       // default

要转换一个节点数组,我们写transformAll -

const transformAll = (arr = []) =>
  arr .flatMap (transform1)

如您所见,transformAll 调用transform1,后者也调用transformAll。这种技术称为mutual recursion,它是一种处理递归数据结构的好方法,就像您在问题中提出的那样。

为确保我们的功能正常工作,我修改了树以包含更多数据场景。请注意,我们的程序适用于任何具有children 属性的节点。所有其他属性都显示在结果中 -

const data =
  [ { name: "a"
    , children:
        [ { name: "a.a"
          , children: 
              [ { name: "a.a.a"
                , children: []
                }
              , { name: "a.a.b"
                , foo: 123
                , children: []
                }
              ]
          }
        ]
    }
  , { name: "b"
    , children:
        [ { name: "b.a"
          , children: 
              [ { name: "b.a.a"
                , children: []
                }
              , { name: "b.a.b"
                , children: []
                }
              ]
          }
        , { name: "b.b"
          , children: []
          }
        ]
    }
  , { name: "c"
    , children: []
    }
  ]

我们可以在您的数据上运行transformAll 来转换所有个节点 -

transformAll (data)
// [ { name: 'a.a.a' }
// , { name: 'a.a.b', foo: 123 }
// , { name: 'b.a.a' }
// , { name: 'b.a.b' }
// , { name: 'b.b' }
// , { name: 'c' }
// ]

或者要转换一个单个节点,我们调用transform1 -

transform1 (data[0])
// [ { name: 'a.a.a' }
// , { name: 'a.a.b', foo: 123 }
// ]

transform1 (data[2])
// [ { name: 'c' } ]

展开下面的sn-p,在自己的浏览器中验证结果-

const data =
  [ { name: "a"
    , children:
        [ { name: "a.a"
          , children: 
              [ { name: "a.a.a"
                , children: []
                }
              , { name: "a.a.b"
                , foo: 123
                , children: []
                }
              ]
          }
        ]
    }
  , { name: "b"
    , children:
        [ { name: "b.a"
          , children: 
              [ { name: "b.a.a"
                , children: []
                }
              , { name: "b.a.b"
                , children: []
                }
              ]
          }
        , { name: "b.b"
          , children: []
          }
        ]
    }
  , { name: "c"
    , children: []
    }
  ]

const transform1 = ({ children = [], ...node }) =>
  children.length === 0         // leaf
    ? [ node ]
: children.length === 1         // singleton
    ? transform1 (...children)
: transformAll (children)       // default

const transformAll = (arr = []) =>
  arr .flatMap (transform1)

console .log (transformAll (data))

// [ { name: 'a.a.a' }
// , { name: 'a.a.b', foo: 123 }
// , { name: 'b.a.a' }
// , { name: 'b.a.b' }
// , { name: 'b.b' }
// , { name: 'c' }
// ]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 2019-02-17
    • 2022-01-21
    • 2021-02-08
    • 1970-01-01
    • 2017-08-17
    相关资源
    最近更新 更多