Marine Le Borgne
Marine Le Borgne

Reputation: 1056

Javascript filter not working with multiple conditions

Let's assume I have this array :

array = [{ 
    name: 'my post',
    categories: [{
        slug: 'a-cat',
        name: 'A Category'
    }
},
{ 
    name: 'my other post',
    categories: [{
        slug: 'another-category',
        name: 'Another Category'
    },
    {
        slug: 'a-cat',
        name: 'A Category'
    }
},
]  

Now, I would like to filter it to get all element that contain the category another-category, this is what i've tried so far, but nothing ends up in the filteredArray

let filteredArray = array.filter(function (item) {
    return item.categories.forEach(function(cat) {
        return cat.slug === 'another-category'
    })
})

Any thoughts on what I've done wrong ?

const array = [{
    name: 'my post',
    categories: [{
      slug: 'a-cat',
      name: 'A Category'
    }]
  },
  {
    name: 'my other post',
    categories: [{
        slug: 'another-category',
        name: 'Another Category'
      },
      {
        slug: 'a-cat',
        name: 'A Category'
      }
    ]
  },
]


let filteredArray = array.filter(function(item) {
  return item.categories.forEach(function(cat) {
    return cat.slug === 'another-category'
  })
})

console.log(filteredArray)

Upvotes: 1

Views: 681

Answers (3)

Kai
Kai

Reputation: 3663

Seem you misunderstand the return value of forEach. In your example code, item.category.forEach() will always return undefined when it finishes execution, that's why it went wrong.

In this case, you should use Array.some() which with return value is boolean (true/false).

let filteredArray = array.filter(function (item) {
    // this mean:
    //  if has ANY <cat>s in array item.categories has slug attribute equal 'another-category': 
    //  return current <item>
    return item.categories.some(function(cat) {
        return cat.slug === 'another-category'
    })
})

**An alternative answer is using .every():

let filteredArray = array.filter(function (item) {
        // this mean:
        //  if NOT(ALL <cat>s in array item.categories haven't .slug attribute  equal  'another-category'): 
        //  return current <item>
        return !item.categories.every(function(cat) {
            return (return cat.slug !== 'another-category')
        });
})

note: the .every() is just an additional example, in case of you guys need it in the future :)!

Upvotes: 2

Prasun
Prasun

Reputation: 5023

You can use find method over categories to filter final list

let filteredArray = array.filter(item => {
    return item.categories.find( category => category.slug === 'another-category');
});

Upvotes: 1

Vivek
Vivek

Reputation: 4886

What you need here is some. Replace forEach with some.

return item.categories.some(function(cat) {
    return cat.slug === 'another-category'
})

Upvotes: 1

Related Questions