1

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)

2
  • 2
    forEach returns undefined which is treated as false in filter. What is your desired result? Commented Apr 28, 2018 at 18:23
  • 1
    I fixed your object and created a snippet Commented Apr 28, 2018 at 18:25

3 Answers 3

2

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 :)!

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

Comments

1

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

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

Comments

1

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

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.