web-dev-qa-db-ja.com

ネストされた値に基づく配列でオブジェクトの配列をフィルタリングする

ネストされたオブジェクトに基づいて、配列をフィルタリングしようとしています。いくつか用意しました フィドル

入力配列は次のようになります。

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));

出力はほぼ良好ですが、姓を含むすべてのオブジェクトを含むオブジェクトを返します(フィドル:Dを確認することをお勧めします)。フィルタリングを改善するにはどうすればよいですか?

14
bartosz.baczek

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');
  });

ここでは、元の配列を操作したくないと想定しています。したがって、私はObject.assignを使用しています。

22
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)});

  }); 
10
Mohak Londhe

これにより、配列内の必要な深さまで移動し、任意のレベルで要素をフィルタリングできます

arrayOfElements.map((element) => {
  return {...element, subElements: element.subElements.filter((subElement) => subElement.surname === 1)}
})

Spread operatorelementを展開し、フィルターされた値でsubElementsキーをオーバーライドします。

5
Nitesh Ranjan

この解決策を試してください:

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

上記の答えを改善した

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)
4

あなたもそれをジェネリックにすることができます:

論理

  • 明確な姓をすべて検索してループする
  • すべてのオブジェクトをフィルタリングして、姓が存在するかどうかを確認します。はいの場合は、 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)

注:矢印関数は、thisの参照を維持するために使用されます。関数内でthisを使用していない場合は、通常の関数も使用できます。

1
Rajesh
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;
    });

より正確です

1
Ilya Alexeev
_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"/>
1
Himanshu Tyagi