鉴于以下数据结构:
[
{
"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":[
]
}
]如果只有一个孩子,我想删除一个级别。在本例中,我希望有一个新数组,它只包含" root“级别的子级,而不包含根本身。
我会用reduce来做这件事,但仍然不能把我的头放在reduce和递归的结合上。有什么想法吗?
发布于 2019-03-13 10:42:57
之后,您可以简单地使用map和平面数组。 .map(o => o.children).flat()
编辑:在找出真正的问题后更新的答案
尽管如此,您仍然可以使用map和平面逻辑,但可以使用递归方式。
function removeSingleChildElms (o) {
if (!o.children) return
if (o.children.length === 1) {
return o.children.map(removeSingleChildElms).flat()
} else {
return o.children
}
}EDIT2:一些解释:问题是将对象数组转换为不同对象的数组。我不选择减少,因为问题并不关心兄弟元素之间的关系/逻辑。它只是关于转换,因此地图将工作得足够好。
该问题要求“跳过”带有一个子对象的对象。这是反复出现的部分,意思是:如果您看到一个满足此条件的对象,则需要进行更深层次的映射。在任何其他有效条件下,儿童保持不变(否则)
发布于 2019-03-13 14:37:55
可以通过将任务分解为两部分来简化树转换:
要转换单个节点,我们编写transform1
transformAllconst 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。这种技术被称为互递归,它是处理递归数据结构的一种很好的方法,就像您在问题中提出的那样。
为了确保我们的函数正常工作,我修改了树以包含更多的数据场景。注意,我们的程序适用于任何具有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' } ]展开下面的代码片段,在自己的浏览器中验证结果-
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' }
// ]
https://stackoverflow.com/questions/55139385
复制相似问题