Filtering array of objects with arrays based on nested value

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.


After you call filter, you need to pipe the results to map, like this:

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.


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)

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

  });