[英]Filtering array of objects with arrays based on nested value
I am trying to filter an array, based on some nested object. I prepared some Fiddle我正在尝试根据一些嵌套的 object 过滤一个数组。我准备了一些Fiddle
Input array looks like this:输入数组如下所示:
let arrayOfElements =
[
{
"name": "a",
"subElements":
[
{"surname": 1},
{"surname": 2}
]
},
{
"name": "b",
"subElements":
[
{"surname": 3},
{"surname": 1}
]
},
{
"name": "c",
"subElements":
[
{"surname": 2},
{"surname": 5}
]
}
];
I want the output for this case, to look like this:对于这种情况,我希望 output 看起来像这样:
let filteredArray =
[
{
"name": "a",
"subElements":
[
{"surname": 1}
]
},
{
"name": "b",
"subElements":
[
{"surname": 1}
]
}
];
I am using this formula to do that:我正在使用这个公式来做到这一点:
let filteredArray = arrayOfElements.filter((element) => element.subElements.some((subElement) => subElement.surname === 1));
Output is almost good, but it returns objects with all objects with surnames (better check that fiddle:D), instead of cutting them away. Output 几乎不错,但它返回的对象包含所有带有姓氏的对象(最好检查小提琴:D),而不是将它们删除。 How can i improve the filtering?我怎样才能改进过滤?
This way you can go as deep as you want in an array and filter elements at any level,通过这种方式,您可以在任何级别的数组中尽可能深入并过滤元素,
arrayOfElements.map((element) => {
return {...element, subElements: element.subElements.filter((subElement) => subElement.surname === 1)}
})
Spread operator
will expand element
and then filtered subElements
will override the subElements
in element. Spread operator
将扩大element
,然后过滤subElements
将覆盖subElements
的元素。
After you call filter
, you need to pipe the results to map
, like this:调用filter
,您需要将结果通过管道传送到map
,如下所示:
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');
});
I am assuming here that you don't want to manipulate the original array.我在这里假设您不想操作原始数组。 So, I am using Object.assign.所以,我正在使用 Object.assign。
let filteredArray = arrayOfElements
.filter((element) =>
element.subElements.some((subElement) => subElement.surname == 1))
.map(element => {
return Object.assign({}, element, {subElements : element.subElements.filter(subElement => subElement.surname == 1)});
});
Try this solution:试试这个解决方案:
data_filter = arrayOfElements.filter(function (element) {
return element.subElements.some( function (subElement) {
return subElement.surname === surname
});
});
Just improved the answers above刚刚改进了上面的答案
let elements = [ { "name": "a", "subElements": [ {"surname": 1}, {"surname": 2} ] }, { "name": "b", "subElements": [ {"surname": 3}, {"surname": 1} ] }, { "name": "c", "subElements": [ {"surname": 2}, {"surname": 5} ] } ]; var value = 1; var filteredArray = elements .filter(element => element.subElements .some(subElement => subElement.surname === value) ) .map(element => { let n = Object.assign({}, element, {'subElements': element.subElements.filter( subElement => subElement.surname === value )}) return n; }) console.log(filteredArray)
function display_message() { let arrayOfElements = [{ "name": "a", "subElements": [{ "surname": 1 }, { "surname": 2 }] }, { "name": "b", "subElements": [{ "surname": 3 }, { "surname": 1 }] }, { "name": "c", "subElements": [{ "surname": 2 }, { "surname": 5 }] }]; // console.log(arrayOfElements); var surname = 1; let filteredArray = arrayOfElements.filter((element) => element.subElements.some((subElement) => subElement.surname === surname)); for(var data in filteredArray){ filteredArray[data].subElements = {"surname": surname}; } console.log(filteredArray); }
<input type="button" onclick="display_message();" value="click"/>
You can make it generic as well:您也可以使其通用:
subElements
value to filtered list.如果是,请使用Object.assign复制对象并将subElements
值设置为过滤列表。 let arrayOfElements=[{name:"a",subElements:[{surname:1},{surname:2}]},{name:"b",subElements:[{surname:3},{surname:1}]},{name:"c",subElements:[{surname:2},{surname:5}]}]; let distinct_surnames = []; arrayOfElements.forEach(function(el) { el.subElements.forEach(function(s) { if (distinct_surnames.indexOf(s.surname) < 0) distinct_surnames.push(s.surname) }); }) let result = []; distinct_surnames.forEach(function(sn) { let inter = []; arrayOfElements.forEach(function(el) { let f = el.subElements.filter(function(sub) { return sub.surname === sn; }); if (f.length > 0) { let _tmp = Object.assign({}, el); _tmp.subElements = f; inter.push(_tmp); } }); result.push(inter); }) console.log(result)
Note: Arrow functions are used to keep the reference of this
.注意:箭头函数用于保持this
的引用。 If you are not using this
inside function, you can use normal functions as well.如果你不使用this
内部函数,你也可以使用普通函数。
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;
});
is more correctly更正确
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.