我已经花了一段时间思考这个问题,以为也许是时候在这里发布了。
我有一个复杂的对象结构,可以在任何级别的深度都有一个嵌套项。这是一个例子:
{
resourceType: 'QuestionnaireResponse',
item: [
{
linkId: 'Floors',
answer: []
},
{
linkId: 'KID',
answer: [
{
valueBoolean: false
}
]
},
{
linkId: 'Age',
answer: [
{
valueString: '≥30 Years'
}
]
},
{
linkId: 'UnicornGroup',
item: [
{
linkId: 'DoYouLikeUnicorns',
answer: [{valueBoolean: true}]
},
{
linkId: 'DoYouLikeFHIR'
}
],
answer: []
}
]
}
我想结束一个看起来像这样的对象:
{
resourceType: 'QuestionnaireResponse',
item: [
{
linkId: 'KID',
answer: [
{
valueBoolean: false
}
]
},
{
linkId: 'Age',
answer: [
{
valueString: '≥30 Years'
}
]
},
{
linkId: 'UnicornGroup',
item: [
{
linkId: 'DoYouLikeUnicorns',
answer: [{valueBoolean: true}]
}
]
}
]
}
那就是我想过滤掉具有空答案数组的项目对象,而没有具有非空答案数组的嵌套对象。
这是我所拥有的,但不起作用:
var res = fItems.filter(function f(o) {
if (o.answer && o.answer.length > 0) {
return true
} else {
if(o.item){
return f(o.item);
}
}
});
我创建了一个REPL Here。我们在项目中使用ramda,因此如果解决方案使用ramda也可以。感谢您的时间。
最佳答案
我认为filter()
实际上是错误的工具,因为它无法轻松处理要递归过滤item
数组的情况。为此,您需要将items
属性设置为新的过滤后的数组,然后最终对原始数组进行变异。也许更好的方向是通过添加所需项而不是过滤来构建一个新数组。在不是带有子项数组的组的项中,情况很简单-如果它们有答案,则只需添加即可。但是,这些项目必须以不同的方式处理。也许这样会有所帮助:
let obj = {resourceType: 'QuestionnaireResponse',item: [{linkId: 'Floors',answer: []},{linkId: 'KID',answer: [{valueBoolean: false}]},{linkId: 'Age',answer: [{valueString: '≥30 Years'}]},{linkId: 'UnicornGroup',item: [{linkId: 'DoYouLikeUnicorns',answer: [{valueBoolean: true}]},{linkId: 'DoYouLikeFHIR'}],answer: []}]}
function filterAnswers(item_arr){
return item_arr.reduce((arr, current) => {
// deal with groups
if (current.item && current.item.length){
let item = filterAnswers(current.item)
if (item.length) {
let ret_obj = {linkId: current.linkId, item:item}
arr.push(ret_obj)
}
}
// deal with the simple case
else if(current.answer && current.answer.length)
arr.push(current)
return arr
}, [])
}
let filtered_items = filterAnswers(obj.item)
console.log(filtered_items)
为了使代码简单,我假装(也许)复合组的
answers
属性始终为空。从示例中尚不清楚这些项目是否可能具有answers
和空的item
数组,或者同时具有item
和answer
。无论哪种方式,都只是测试并在推送之前将其添加到对象中。