Javascript 使用基于嵌套值的数组筛选对象数组

Javascript 使用基于嵌套值的数组筛选对象数组,javascript,filtering,Javascript,Filtering,我正在尝试根据某个嵌套对象筛选数组。我准备了一些 输入数组如下所示: let arrayOfElements = [ { "name": "a", "subElements": [ {"surname": 1}, {"surname": 2} ] }, { "name": "b

我正在尝试根据某个嵌套对象筛选数组。我准备了一些

输入数组如下所示:

let arrayOfElements = 
    [
        {
           "name": "a",
           "subElements": 
           [
             {"surname": 1},
             {"surname": 2}
           ]
        },
        {
           "name": "b",
           "subElements": 
           [
             {"surname": 3},
             {"surname": 1}
           ]
        },
        {
           "name": "c",
           "subElements": 
           [
             {"surname": 2},
             {"surname": 5}
           ]
        }
    ];
let filteredArray = 
    [
        {
          "name": "a",
          "subElements": 
          [
            {"surname": 1}
          ]
        },
        {
          "name": "b",
          "subElements": 
          [
            {"surname": 1}
          ]
        }
];
let filteredArray = arrayOfElements
  .filter((element) => 
    element.subElements.some((subElement) => subElement.surname === 1))
  .map(element => {
    let newElt = Object.assign({}, element); // copies element
    return newElt.subElements.filter(subElement => subElement.surname === '1');
  });
我希望本例的输出如下所示:

let arrayOfElements = 
    [
        {
           "name": "a",
           "subElements": 
           [
             {"surname": 1},
             {"surname": 2}
           ]
        },
        {
           "name": "b",
           "subElements": 
           [
             {"surname": 3},
             {"surname": 1}
           ]
        },
        {
           "name": "c",
           "subElements": 
           [
             {"surname": 2},
             {"surname": 5}
           ]
        }
    ];
let filteredArray = 
    [
        {
          "name": "a",
          "subElements": 
          [
            {"surname": 1}
          ]
        },
        {
          "name": "b",
          "subElements": 
          [
            {"surname": 1}
          ]
        }
];
let filteredArray = arrayOfElements
  .filter((element) => 
    element.subElements.some((subElement) => subElement.surname === 1))
  .map(element => {
    let newElt = Object.assign({}, element); // copies element
    return newElt.subElements.filter(subElement => subElement.surname === '1');
  });
我用这个公式来做:

let filteredArray = arrayOfElements.filter((element) => element.subElements.some((subElement) => subElement.surname === 1));

输出几乎不错,但它返回的对象中包含所有带有姓氏的对象(最好检查fiddle:D),而不是将它们删除。如何改进过滤?

在调用
过滤器
后,需要将结果通过管道传输到
映射
,如下所示:

let arrayOfElements = 
    [
        {
           "name": "a",
           "subElements": 
           [
             {"surname": 1},
             {"surname": 2}
           ]
        },
        {
           "name": "b",
           "subElements": 
           [
             {"surname": 3},
             {"surname": 1}
           ]
        },
        {
           "name": "c",
           "subElements": 
           [
             {"surname": 2},
             {"surname": 5}
           ]
        }
    ];
let filteredArray = 
    [
        {
          "name": "a",
          "subElements": 
          [
            {"surname": 1}
          ]
        },
        {
          "name": "b",
          "subElements": 
          [
            {"surname": 1}
          ]
        }
];
let filteredArray = arrayOfElements
  .filter((element) => 
    element.subElements.some((subElement) => subElement.surname === 1))
  .map(element => {
    let newElt = Object.assign({}, element); // copies element
    return newElt.subElements.filter(subElement => subElement.surname === '1');
  });
我在这里假设您不想操纵原始数组。因此,我使用Object.assign

功能显示\信息(){
设ArrayOfelments=[{
“姓名”:“a”,
“子元素”:[{
“姓”:1
}, {
“姓”:2
}]
}, {
“名称”:“b”,
“子元素”:[{
“姓”:3
}, {
“姓”:1
}]
}, {
“姓名”:“c”,
“子元素”:[{
“姓”:2
}, {
“姓”:5
}]
}];
//控制台日志(arrayOfElements);
var姓氏=1;
让filterDarray=ArrayOfelments.filter((element)=>element.subElements.some((subElement)=>subElement.nam姓氏===姓氏));
for(filteredArray中的var数据){
filteredArray[数据]。子元素={“姓氏”:姓氏};
}
控制台日志(filteredArray);
}

您也可以将其设置为通用:

逻辑
  • 找到所有不同的姓氏,并在上面循环
  • 筛选每个对象以检查是否存在姓氏。如果是,请使用复制对象并将
    子元素
    值设置为筛选列表
  • 创建一个临时数组以容纳所有相似的对象,并将复制的对象推送到该数组中
  • 在每个不同姓氏的迭代中,将此数组推送到最终数组
样品
let arrayOfElements=[{name:“a”,子元素:[{name:1},{name:2}],{name:“b”,子元素:[{name:3},{name:1}],{name:“c”,子元素:[{name:2},{name:5}];
让不同的姓=[];
ArrayOfelments.forEach(函数(el){
el.subElements.forEach(函数){
if(不同姓氏。索引of(s姓氏)<0)不同姓氏。push(s姓氏)
});
})
让结果=[];
不同的姓氏。forEach(函数(sn){
让inter=[];
ArrayOfelments.forEach(函数(el){
设f=el.subElements.filter(函数(sub)){
返回子姓===sn;
});
如果(f.长度>0){
设_tmp=Object.assign({},el);
_tmp.subElements=f;
内部推送(tmp);
}
});
结果:推送(inter);
})
console.log(结果)
尝试以下解决方案:

data_filter = arrayOfElements.filter(function (element) {
    return element.subElements.some( function (subElement) {
        return subElement.surname === surname
    });
});

只是改进了上面的答案

let元素=
[
{
“姓名”:“a”,
“子元素”:
[
{“姓氏”:1},
{“姓氏”:2}
]
},
{
“名称”:“b”,
“子元素”:
[
{“姓氏”:3},
{“姓氏”:1}
]
},
{
“姓名”:“c”,
“子元素”:
[
{“姓氏”:2},
{“姓氏”:5}
]
}
];
var值=1;
var filteredArray=元素
.filter(element=>element.subElements
.some(subElement=>subElement.nam姓氏===value)
)
.map(元素=>{
设n=Object.assign({},element,{'subElements':element.subElements.filter(
子元素=>子元素。姓氏===值
)})
返回n;
})

log(filteredArray)
通过这种方式,您可以在数组和任何级别的过滤器元素中进行任意深度的过滤,

arrayOfElements.map((element) => {
  return {...element, subElements: element.subElements.filter((subElement) => subElement.surname === 1)}
})
扩展运算符
将展开
元素
,然后过滤的
子元素
将覆盖元素中的
子元素

let filteredArray = arrayOfElements
    .filter((element) => 
        element.subElements.some((subElement) => subElement.surname === 1))
    .map(element => {
        let newElt = Object.assign({}, element); // copies element
        newElt.subElements = newElt.subElements.filter(subElement => subElement.surName === '1'); 
        return newElt;
    });

是否更正确

您是否尝试根据姓氏进行分组?我的意思是同样的事情应该分为
a
c
,因为他们有姓
2
。对吗?这不是只返回子元素数组而不是带有过滤子数组的完整对象吗?@WannyMiarelli是正确的。它将返回过滤后的子数组,而不是带有过滤后姓氏的完整对象。此外,上面的代码也有错误(字符串检查而不是整数和键入姓氏)。此解决方案不会产生预期的输出:@Lokeshanapalli,在对
过滤器的最后调用中
您需要将
姓氏
更改为
姓氏
。然后它就起作用了。这是我上面的错误。现在更正。嗨@AndrewEisenberg!谢谢你的意见。4年后的今天,我决定将公认的答案改为使用spread运算符,因为它似乎更适合2020年:)谢谢,我希望没有什么不快:)当您将过滤后的数组与父对象“subElement”合并时,这将给出预期的响应。这返回了预期的响应。非常感谢。Hit不会返回准确的预期响应,但会返回找到的对象中的所有姓氏。这应该是答案,因为接受的答案不会产生预期的输出。是的,此答案更好。写入接受的答案时,对象排列运算符不存在。这是在修改原始值array@Aadam你能分享你的阵列吗?Array.map不修改原始数组,但返回一个具有修改值的新数组。