8

I have an array, which looks like this:

const persons = [
  {
    name: "Joe",
    animals: [
      {species: "dog", name: "Bolt"},
      {species: "cat", name: "Billy"},
    ]
  },
  {
    name: "Bob",
    animals: [
      {species: "dog", name: "Snoopy"}
    ]
  }
];

Now I want to filter based on the species. For example: every person which has a cat, should be returned:

const result = [
  {
    name: "Joe",
    animals: [
      {species: "dog", name: "Bolt"},
      {species: "cat", name: "Billy"},
    ]
  }
];

I have tried with the the filter() method like this:

const result = persons.filter(p => p.animals.filter(s => s.species === 'cat'))

But this doesn't return the desired result (it returns both persons).

How can I filter the array bases on an attribute of a nested array?

2

7 Answers 7

14

Your inner filter still returns a "truthy" value (empty array) for the dog person. Add .length so that no results becomes 0 ("falsey")

const result = persons.filter(p => p.animals.filter(s => s.species === 'cat').length)

Edit: Per comments and several other answers, since the goal is to get a truthy value from the inner loop, .some would get the job done even better because it directly returns true if any items match.

const result = persons.filter(p => p.animals.some(s => s.species === 'cat'))

Sign up to request clarification or add additional context in comments.

Comments

4

You might want to use some'

 persons.filter(p => p.animals.some(s => s.species === 'cat'))

Comments

1

const persons = [
  {
    name: "Joe",
    animals: [
      {species: "dog", name: "Bolt"},
      {species: "cat", name: "Billy"},
    ]
  },
  {
    name: "Bob",
    animals: [
      {species: "dog", name: "Snoopy"}
    ]
  }
];

Filter = function(arr, a){
  return arr.filter(t=>t.animals.filter(y=>y.species==a).length>0);
}

console.log(Filter(persons, 'cat'))

Comments

0

You can use filter() with some() method to check if some of the objects in animals array has species == cat.

const persons = [{"name":"Joe","animals":[{"species":"dog","name":"Bolt"},{"species":"cat","name":"Billy"}]},{"name":"Bob","animals":[{"species":"dog","name":"Snoopy"}]}]

const result = persons.filter(({animals}) => {
  return animals.some(({species}) => species == 'cat')
})

console.log(result)

Comments

0

This should do the trick

persons.filter((person) => {
    return person.animals.filter((animal) => {
        return animal.species === 'cat';
    }).length > 0;
});

Add the check on length, as filter returns an array, not a boolean.

Comments

0

You havent checked against the length of the second filter.

Filer only includes results that return a true value. So we need to provide the second filter with a way of returning true if it finds something. We can do that by saying, if the returned array is > 0

const persons = [
  {
    name: "Joe",
    animals: [
      {species: "dog", name: "Bolt"},
      {species: "cat", name: "Billy"},
    ]
  },
  {
    name: "Bob",
    animals: [
      {species: "dog", name: "Snoopy"}
    ]
  }
];

const filtered = persons.filter(p => p.animals.filter(a => a.species === "cat").length > 0)

console.log(filtered)

Comments

0

This should work!

const result = persons.filter(person => {
   let innerResult = person.animals.filter(animal => {
      return animal.species === 'cat';
   });

  return innerResult.length > 0;
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.