0

I have two arrays. One holds products, the other holds filters (Shirts, Pants, etc). All products have a type property which could be shirts, pants, etc, corresponding to the filters.

I'm trying to make a selector that will return a new array missing any of the products that have a type that matches any of the filters.

export function filterProducts(products, filters) {
  return products.filter((item) => {
    return item.type === "hat";
  });
};

Similar to this, except instead obviously checking against every filter, not just "hat". I can think of some janky ways to implement this, but I'm trying to figure out something more elegant. I know I have to loop inside of a loop, but I can't quite get it to work correctly. ES6/lodash, etc are fine.

3
  • 1
    You could use some, indexOf, or includes, which are all array methods. Commented Mar 22, 2017 at 4:08
  • 2
    item => filters.includes(item.type)? Commented Mar 22, 2017 at 4:10
  • 1
    Let me get this straight: you want to keep the ones matching the filters or the other way around? Your post contradicts itself... Commented Mar 22, 2017 at 4:31

2 Answers 2

1

Assuming that filters is an array of strings containing the types you are looking for, you could use Array.prototype.some to search the filters array to filter it.

var products = [
    {
      name: 'Foo',
      type: 'hat'
    },
    {
      name: 'Bar',
      type: 'shirt'
    },
    {
      name: 'Baz',
      type: 'pants'
    },
    {
      name: 'Foobar',
      type: 'hat'
    },
    {
      name: 'Falsy Type',
      type: ''
    },
  ],
  filters = ['hat', 'pants', ''];

function filterProducts(products, filters) {
  return products.filter((item) => {
    return !filters.some(filter => item.type === filter);
  });
};

console.log(filterProducts(products, filters));

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

7 Comments

I actually gave the wrong code snippet and it probably made answering my question confusing. I ended up using: !filters.find(filter => item.type === filter) Which gave me the desired result. Thanks for your help:)
@Ian Ah, I seem to have glossed over the "missing any" in the text. I've updated the answer to reflect what you were going for.
No, you should use some instead of find to check whether an element exists in an array. Imagine item.type being falsy…
@Bergi find would only fail if there was both a falsy item.type and a matching falsy item in filters; since filters is an array of non-empty strings (thus always truthy), barring a typo find works. That said, you're right that some is a be better fit for this, it makes it more bullet-proof. I've updated the example.
Thanks! Btw, if you care about outdated browsers that don't support some, there's only IE8 and that would even need a polyfill for indexOf
|
1

Another take on this !

'use strict'
const filters = ['hat','shirt','pant'];
const products = [{
                    sku: 101,
                    type: 'hat'
                 }, {
                    sku: 102,
                    type: 'hat'
                 }, {
                    sku: 103,
                    type: 'shirt'
                 }, {
                    sku: 104,
                    type: 'pant'
                 }, {
                    sku: 101,
                    type: 'pant'
                 }, {
                    sku: 101,
                    type: 'shirt'
                 }]


const filterize = function (products, filters){
    let map = {};
    filters.forEach(function(filter){
        map[filter] = [];
    })
    products.forEach(function(product){
        if(typeof map[product.type] !== undefined){
            map[product.type].push(product);
        }
    })
    return map;
}


console.log(filterize(products, filters));

This will return a map with your filters as keys and values as the product list corresponding to the filter. Sample output below :

{ hat: [ { sku: 101, type: 'hat' }, { sku: 102, type: 'hat' } ],
  shirt: [ { sku: 103, type: 'shirt' }, { sku: 101, type: 'shirt' } ],
  pant: [ { sku: 104, type: 'pant' }, { sku: 101, type: 'pant' } ] }

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.