简体   繁体   English

根据嵌套值过滤具有 arrays 的对象数组

[英]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:您也可以使其通用:

Logic逻辑

  • Find all distinct surnames and loop over them找到所有不同的姓氏并遍历它们
  • Filter every object to check if surnames exists.过滤每个对象以检查姓氏是否存在。 If yes, copy object using Object.assign and set subElements value to filtered list.如果是,请使用Object.assign复制对象并将subElements值设置为过滤列表。
  • Create a temp array to hold all similar objects and push copied object to it.创建一个临时数组来保存所有相似的对象并将复制的对象推送到它。
  • Push this array to final array on every iteration of distinct surname.在不同姓氏的每次迭代中将此数组推送到最终数组。

Sample样品

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM