Filter multidimensional array that contains a certain value

Viewed 4662

I have an array...

var families = [
  {
    family:"Jones",
    kids: [
      {name:"Kelly", gender:'female'},
      {name:"Mike", gender:'male'},
      {name:"Bill", gender:'male'}
    ]
  },{
    family:"Smiths",
    kids: [
      {name:"Roger", gender:'male'}
    ]
  }
]

...that I need filter through and sort out familys by gender. So if I search for 'female' I want an array of families that contain females in their family. Regardless if there is a male in the family. So in the above code, if I search for female, only one family would return. But if I searched by male, 2 families would return.

My try looks like this:

var filter = 'female';
filteredList = families.filter(function (family) {
  return family.kids.filter(function (kid) {
    return kid.gender.toLowerCase().indexOf(filter) !== -1;
  })
})

Am I not returning it properly?

3 Answers

You should just use filter and some like so:

var families=[{family:"Jones",kids:[{name:"Kelly",gender:'female'},{name:"Mike",gender:'male'},{name:"Bill",gender:'male'}]},{family:"Smiths",kids:[{name:"Roger",gender:'male'}]}];
var filter = "female";
const res = families.filter(({ kids }) => kids.some(({ gender }) => gender == filter));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }

ES5 syntax:

var families=[{family:"Jones",kids:[{name:"Kelly",gender:'female'},{name:"Mike",gender:'male'},{name:"Bill",gender:'male'}]},{family:"Smiths",kids:[{name:"Roger",gender:'male'}]}];
var filter = "female";
var res = families.filter(function(family) {
  return family.kids.some(function(kid) {
    return kid.gender == filter;
  })
});
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }

Your code is basically there except for one small detail: your inner filter returns an empty array to the outer filter, which is always evaluated as true. Add .length to the inner array to make empty arrays falsey:

var families = [ { family:"Jones", kids: [ {name:"Kelly", gender:'female'}, {name:"Mike", gender:'male'}, {name:"Bill", gender:'male'} ] },{ family:"Smiths", kids: [ {name:"Roger", gender:'male'} ] } ];

var filter = 'female';
filteredList = families.filter(function (family) {
  return family.kids.filter(function (kid) {
    return kid.gender.toLowerCase().indexOf(filter) !== -1;
  }).length
  //^^^^^^^
});

console.log(filteredList);

You can use forEach and some. forEach will be used to iterate over the array and use some to find if any object in kids have the required gender.

var families = [{
  family: "Jones",
  kids: [{
      name: "Kelly",
      gender: 'female'
    },
    {
      name: "Mike",
      gender: 'male'
    },
    {
      name: "Bill",
      gender: 'male'
    }
  ]
}, {
  family: "Smiths",
  kids: [{
    name: "Roger",
    gender: 'male'
  }]
}];


let filteredData = function(arr, gender) {
  let filteredFamily = [];
  arr.forEach(function(elem) {
    let ifHasGender = elem.kids.some(function(item) {
      return item.gender === gender
    })
    if (ifHasGender) {
      filteredFamily.push(elem)
    }
  })

  return filteredFamily;
}

console.log(filteredData(families, 'female'))

Related