我在这个问题上绞尽脑汁已经有一段时间了,我想也许是时候在这里发帖了。
我有一个复杂的对象结构,它可以有一个嵌套的项目属性,任何级别都可以。下面是一个示例:
{
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}]
}
]
}
]
}
也就是说,我希望过滤掉具有空答案数组的item对象,并且不具有具有非空答案数组的嵌套对象。
这就是我所拥有的,但它不工作:
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,也没问题。谢谢你抽出时间来。
发布于 2018-10-18 06:56:15
我认为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
。无论哪种方式,在推送之前,只需测试并将其添加到对象即可。
发布于 2018-10-18 08:15:34
这里有一种可能性:
const filterAnswers = ({item = [], ...rest}) => {
const items = item.map(filterAnswers).filter(
node => (node.answer && node.answer.length)
|| (node.item && node.item.length)
)
return Object.assign({...rest}, items.length ? {item: items} : {})
}
const allItems = {"item": [{"answer": [], "linkId": "Floors"}, {"answer": [{"valueBoolean": false}], "linkId": "KID"}, {"answer": [{"valueString": "≥30 Years"}], "linkId": "Age"}, {"answer": [], "item": [{"answer": [{"valueBoolean": true}], "linkId": "DoYouLikeUnicorns"}, {"linkId": "DoYouLikeFHIR"}], "linkId": "UnicornGroup"}], "resourceType": "QuestionnaireResponse"}
console.log(filterAnswers(allItems))
虽然Ramda (免责声明:我是一个Ramda作者)可能会在边缘(例如filter(either(path(['answer', 'length']), path(['item', 'length'])))
)上有所帮助,但我相信这类问题不会轻易地变得无关紧要,而且我认为Ramda不会增加太多。
发布于 2018-10-18 06:20:37
我想我可以通过递归解决方案来解决这个问题。我们的想法是深入到最深层然后..。请注意此过滤器:
items.filter(i => i.answer || (i.item && i.item.length > 0));
第一个条件很简单,但是我们需要考虑第二个条件,因为在修剪较低的项之后,我们有一个对于对象来说非空的项数组(即使它自己的答案数组是空的)。
let allItems = {
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: []
},
{
linkId: 'DBZGroup', // this object should complete go away too because all of its children will be removed
item: [{
linkId: 'DoYouLikeUnicorns',
answer: []
},
{
linkId: 'DoYouLikeFHIR'
}
],
answer: []
}
]
}
function filter(items) {
items.forEach(i => {
if (i.item && i.item.length > 0) i.item = filter(i.item);
if (i.answer && i.answer.length === 0) delete i.answer;
});
return items.filter(i => i.answer || (i.item && i.item.length > 0));
}
// make a deep copy if you don't want to mutate the original
allItems.item = filter(allItems.item);
console.log(allItems);
https://stackoverflow.com/questions/52864073
复制相似问题