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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.